mirror of
https://github.com/TomHarte/CLK.git
synced 2025-02-22 11:29:20 +00:00
Devolves time to cycle conversion to machines.
Thereby avoids a whole bunch of complicated machinations that would otherwise have been required of the multimachine.
This commit is contained in:
parent
ece3a05504
commit
da3d65c18f
@ -75,41 +75,16 @@ Outputs::Speaker::Speaker *MultiCRTMachine::get_speaker() {
|
||||
return speaker_;
|
||||
}
|
||||
|
||||
void MultiCRTMachine::run_for(const Cycles cycles) {
|
||||
void MultiCRTMachine::run_for(Time::Seconds duration) {
|
||||
perform_parallel([=](::CRTMachine::Machine *machine) {
|
||||
if(machine->get_confidence() >= 0.01f) machine->run_for(cycles);
|
||||
if(machine->get_confidence() >= 0.01f) machine->run_for(duration);
|
||||
});
|
||||
|
||||
if(delegate_) delegate_->multi_crt_did_run_machines();
|
||||
}
|
||||
|
||||
double MultiCRTMachine::get_clock_rate() {
|
||||
// TODO: something smarter than this? Not all clock rates will necessarily be the same.
|
||||
std::lock_guard<std::mutex> machines_lock(machines_mutex_);
|
||||
CRTMachine::Machine *crt_machine = machines_.front()->crt_machine();
|
||||
return crt_machine ? crt_machine->get_clock_rate() : 0.0;
|
||||
}
|
||||
|
||||
bool MultiCRTMachine::get_clock_is_unlimited() {
|
||||
std::lock_guard<std::mutex> machines_lock(machines_mutex_);
|
||||
CRTMachine::Machine *crt_machine = machines_.front()->crt_machine();
|
||||
return crt_machine ? crt_machine->get_clock_is_unlimited() : false;
|
||||
}
|
||||
|
||||
void MultiCRTMachine::did_change_machine_order() {
|
||||
if(speaker_) {
|
||||
speaker_->set_new_front_machine(machines_.front().get());
|
||||
}
|
||||
}
|
||||
|
||||
void MultiCRTMachine::set_delegate(::CRTMachine::Machine::Delegate *delegate) {
|
||||
// TODO:
|
||||
}
|
||||
|
||||
void MultiCRTMachine::machine_did_change_clock_rate(Machine *machine) {
|
||||
// TODO: consider passing along.
|
||||
}
|
||||
|
||||
void MultiCRTMachine::machine_did_change_clock_is_unlimited(Machine *machine) {
|
||||
// TODO: consider passing along.
|
||||
}
|
||||
|
@ -29,7 +29,7 @@ namespace Dynamic {
|
||||
acquiring a supplied mutex. The owner should also call did_change_machine_order()
|
||||
if the order of machines changes.
|
||||
*/
|
||||
class MultiCRTMachine: public CRTMachine::Machine, public CRTMachine::Machine::Delegate {
|
||||
class MultiCRTMachine: public CRTMachine::Machine {
|
||||
public:
|
||||
MultiCRTMachine(const std::vector<std::unique_ptr<::Machine::DynamicMachine>> &machines, std::mutex &machines_mutex);
|
||||
|
||||
@ -57,16 +57,10 @@ class MultiCRTMachine: public CRTMachine::Machine, public CRTMachine::Machine::D
|
||||
void close_output() override;
|
||||
Outputs::CRT::CRT *get_crt() override;
|
||||
Outputs::Speaker::Speaker *get_speaker() override;
|
||||
void run_for(const Cycles cycles) override;
|
||||
double get_clock_rate() override;
|
||||
bool get_clock_is_unlimited() override;
|
||||
void set_delegate(::CRTMachine::Machine::Delegate *delegate) override;
|
||||
void run_for(Time::Seconds duration) override;
|
||||
|
||||
private:
|
||||
// CRTMachine::Machine::Delegate
|
||||
void machine_did_change_clock_rate(Machine *machine) override;
|
||||
void machine_did_change_clock_is_unlimited(Machine *machine) override;
|
||||
|
||||
void run_for(const Cycles cycles) override {}
|
||||
const std::vector<std::unique_ptr<::Machine::DynamicMachine>> &machines_;
|
||||
std::mutex &machines_mutex_;
|
||||
std::vector<Concurrency::AsyncTaskQueue> queues_;
|
||||
|
18
ClockReceiver/TimeTypes.hpp
Normal file
18
ClockReceiver/TimeTypes.hpp
Normal file
@ -0,0 +1,18 @@
|
||||
//
|
||||
// TimeTypes.hpp
|
||||
// Clock Signal
|
||||
//
|
||||
// Created by Thomas Harte on 21/03/2018.
|
||||
// Copyright © 2018 Thomas Harte. All rights reserved.
|
||||
//
|
||||
|
||||
#ifndef TimeTypes_h
|
||||
#define TimeTypes_h
|
||||
|
||||
namespace Time {
|
||||
|
||||
typedef double Seconds;
|
||||
|
||||
}
|
||||
|
||||
#endif /* TimeTypes_h */
|
@ -36,13 +36,11 @@ void BestEffortUpdater::update() {
|
||||
// If the duration is valid, convert it to integer cycles, maintaining a rolling error and call the delegate
|
||||
// if there is one. Proceed only if the number of cycles is positive, and cap it to the per-second maximum —
|
||||
// it's possible this is an adjustable clock so be ready to swallow unexpected adjustments.
|
||||
const int64_t duration = std::chrono::duration_cast<std::chrono::nanoseconds>(elapsed).count();
|
||||
if(duration > 0) {
|
||||
double cycles = ((static_cast<double>(duration) * clock_rate_) / 1e9) + error_;
|
||||
error_ = fmod(cycles, 1.0);
|
||||
|
||||
const int64_t integer_duration = std::chrono::duration_cast<std::chrono::nanoseconds>(elapsed).count();
|
||||
if(integer_duration > 0) {
|
||||
if(delegate_) {
|
||||
delegate_->update(this, static_cast<int>(std::min(cycles, clock_rate_)), has_skipped_);
|
||||
const double duration = static_cast<double>(integer_duration) / 1e9;
|
||||
delegate_->update(this, duration, has_skipped_);
|
||||
}
|
||||
has_skipped_ = false;
|
||||
}
|
||||
@ -70,8 +68,3 @@ void BestEffortUpdater::set_delegate(Delegate *const delegate) {
|
||||
});
|
||||
}
|
||||
|
||||
void BestEffortUpdater::set_clock_rate(const double clock_rate) {
|
||||
async_task_queue_.enqueue([this, clock_rate]() {
|
||||
this->clock_rate_ = clock_rate;
|
||||
});
|
||||
}
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include <chrono>
|
||||
|
||||
#include "AsyncTaskQueue.hpp"
|
||||
#include "TimeTypes.hpp"
|
||||
|
||||
namespace Concurrency {
|
||||
|
||||
@ -30,15 +31,12 @@ class BestEffortUpdater {
|
||||
|
||||
/// A delegate receives timing cues.
|
||||
struct Delegate {
|
||||
virtual void update(BestEffortUpdater *updater, int cycles, bool did_skip_previous_update) = 0;
|
||||
virtual void update(BestEffortUpdater *updater, Time::Seconds duration, bool did_skip_previous_update) = 0;
|
||||
};
|
||||
|
||||
/// Sets the current delegate.
|
||||
void set_delegate(Delegate *);
|
||||
|
||||
/// Sets the clock rate of the delegate.
|
||||
void set_clock_rate(double clock_rate);
|
||||
|
||||
/*!
|
||||
If the delegate is not currently in the process of an `update` call, calls it now to catch up to the current time.
|
||||
The call is asynchronous; this method will return immediately.
|
||||
@ -54,11 +52,9 @@ class BestEffortUpdater {
|
||||
|
||||
std::chrono::time_point<std::chrono::high_resolution_clock> previous_time_point_;
|
||||
bool has_previous_time_point_ = false;
|
||||
double error_ = 0.0;
|
||||
bool has_skipped_ = false;
|
||||
|
||||
Delegate *delegate_ = nullptr;
|
||||
double clock_rate_ = 1.0;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -12,8 +12,11 @@
|
||||
#include "../Outputs/CRT/CRT.hpp"
|
||||
#include "../Outputs/Speaker/Speaker.hpp"
|
||||
#include "../ClockReceiver/ClockReceiver.hpp"
|
||||
#include "../ClockReceiver/TimeTypes.hpp"
|
||||
#include "ROMMachine.hpp"
|
||||
|
||||
#include <cmath>
|
||||
|
||||
namespace CRTMachine {
|
||||
|
||||
/*!
|
||||
@ -41,45 +44,31 @@ class Machine: public ROMMachine::Machine {
|
||||
/// @returns The speaker that receives this machine's output, or @c nullptr if this machine is mute.
|
||||
virtual Outputs::Speaker::Speaker *get_speaker() = 0;
|
||||
|
||||
/// Runs the machine for @c cycles.
|
||||
virtual void run_for(const Cycles cycles) = 0;
|
||||
|
||||
/// @returns The confidence that this machine is running content it understands.
|
||||
virtual float get_confidence() { return 0.5f; }
|
||||
virtual void print_type() {}
|
||||
|
||||
// TODO: sever the clock-rate stuff.
|
||||
virtual double get_clock_rate() {
|
||||
/// Runs the machine for @c duration seconds.
|
||||
virtual void run_for(Time::Seconds duration) {
|
||||
const double cycles = (duration * clock_rate_) + clock_conversion_error_;
|
||||
clock_conversion_error_ = std::fmod(cycles, 1.0);
|
||||
run_for(Cycles(static_cast<int>(cycles)));
|
||||
}
|
||||
|
||||
double get_clock_rate() {
|
||||
return clock_rate_;
|
||||
}
|
||||
virtual bool get_clock_is_unlimited() {
|
||||
return clock_is_unlimited_;
|
||||
}
|
||||
class Delegate {
|
||||
public:
|
||||
virtual void machine_did_change_clock_rate(Machine *machine) = 0;
|
||||
virtual void machine_did_change_clock_is_unlimited(Machine *machine) = 0;
|
||||
};
|
||||
virtual void set_delegate(Delegate *delegate) { delegate_ = delegate; }
|
||||
|
||||
protected:
|
||||
/// Runs the machine for @c cycles.
|
||||
virtual void run_for(const Cycles cycles) = 0;
|
||||
void set_clock_rate(double clock_rate) {
|
||||
if(clock_rate_ != clock_rate) {
|
||||
clock_rate_ = clock_rate;
|
||||
if(delegate_) delegate_->machine_did_change_clock_rate(this);
|
||||
}
|
||||
}
|
||||
void set_clock_is_unlimited(bool clock_is_unlimited) {
|
||||
if(clock_is_unlimited != clock_is_unlimited_) {
|
||||
clock_is_unlimited_ = clock_is_unlimited;
|
||||
if(delegate_) delegate_->machine_did_change_clock_is_unlimited(this);
|
||||
}
|
||||
clock_rate_ = clock_rate;
|
||||
}
|
||||
|
||||
private:
|
||||
Delegate *delegate_ = nullptr;
|
||||
double clock_rate_ = 1.0;
|
||||
bool clock_is_unlimited_ = false;
|
||||
double clock_conversion_error_ = 0.0;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -780,6 +780,7 @@
|
||||
4B448E801F1C45A00009ABD6 /* TZX.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = TZX.hpp; sourceTree = "<group>"; };
|
||||
4B448E821F1C4C480009ABD6 /* PulseQueuedTape.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PulseQueuedTape.cpp; sourceTree = "<group>"; };
|
||||
4B448E831F1C4C480009ABD6 /* PulseQueuedTape.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = PulseQueuedTape.hpp; sourceTree = "<group>"; };
|
||||
4B449C942063389900A095C8 /* TimeTypes.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = TimeTypes.hpp; sourceTree = "<group>"; };
|
||||
4B44EBF41DC987AE00A7820C /* AllSuiteA.bin */ = {isa = PBXFileReference; lastKnownFileType = archive.macbinary; name = AllSuiteA.bin; path = AllSuiteA/AllSuiteA.bin; sourceTree = "<group>"; };
|
||||
4B44EBF61DC9883B00A7820C /* 6502_functional_test.bin */ = {isa = PBXFileReference; lastKnownFileType = archive.macbinary; name = 6502_functional_test.bin; path = "Klaus Dormann/6502_functional_test.bin"; sourceTree = "<group>"; };
|
||||
4B44EBF81DC9898E00A7820C /* BCDTEST_beeb */ = {isa = PBXFileReference; lastKnownFileType = file; name = BCDTEST_beeb; path = BCDTest/BCDTEST_beeb; sourceTree = "<group>"; };
|
||||
@ -2972,6 +2973,7 @@
|
||||
4BF6606A1F281573002CB053 /* ClockReceiver.hpp */,
|
||||
4BB06B211F316A3F00600C7A /* ForceInline.hpp */,
|
||||
4BB146C61F49D7D700253439 /* Sleeper.hpp */,
|
||||
4B449C942063389900A095C8 /* TimeTypes.hpp */,
|
||||
);
|
||||
name = ClockReceiver;
|
||||
path = ../../ClockReceiver;
|
||||
|
@ -12,7 +12,6 @@ import AudioToolbox
|
||||
class MachineDocument:
|
||||
NSDocument,
|
||||
NSWindowDelegate,
|
||||
CSMachineDelegate,
|
||||
CSOpenGLViewDelegate,
|
||||
CSOpenGLViewResponderDelegate,
|
||||
CSBestEffortUpdaterDelegate,
|
||||
@ -56,7 +55,6 @@ class MachineDocument:
|
||||
self.machine.setView(self.openGLView, aspectRatio: Float(displayAspectRatio.width / displayAspectRatio.height))
|
||||
})
|
||||
|
||||
self.machine.delegate = self
|
||||
self.bestEffortUpdater = CSBestEffortUpdater()
|
||||
|
||||
// callbacks from the OpenGL may come on a different thread, immediately following the .delegate set;
|
||||
@ -74,16 +72,6 @@ class MachineDocument:
|
||||
self.bestEffortUpdater!.delegate = self
|
||||
}
|
||||
|
||||
func machineDidChangeClockRate(_ machine: CSMachine!) {
|
||||
setupClockRate()
|
||||
}
|
||||
|
||||
func machineDidChangeClockIsUnlimited(_ machine: CSMachine!) {
|
||||
bestEffortLock.lock()
|
||||
self.bestEffortUpdater?.runAsUnlimited = machine.clockIsUnlimited
|
||||
bestEffortLock.unlock()
|
||||
}
|
||||
|
||||
fileprivate func setupClockRate() {
|
||||
// establish and provide the audio queue, taking advice as to an appropriate sampling rate
|
||||
let maximumSamplingRate = CSAudioQueue.preferredSamplingRate()
|
||||
@ -94,10 +82,6 @@ class MachineDocument:
|
||||
self.machine.audioQueue = self.audioQueue
|
||||
self.machine.setAudioSamplingRate(selectedSamplingRate, bufferSize:audioQueue.preferredBufferSize)
|
||||
}
|
||||
|
||||
bestEffortLock.lock()
|
||||
self.bestEffortUpdater?.clockRate = self.machine.clockRate
|
||||
bestEffortLock.unlock()
|
||||
}
|
||||
|
||||
override func close() {
|
||||
@ -152,21 +136,10 @@ class MachineDocument:
|
||||
}
|
||||
|
||||
// MARK: CSBestEffortUpdaterDelegate
|
||||
final func bestEffortUpdater(_ bestEffortUpdater: CSBestEffortUpdater!, runForCycles cycles: UInt, didSkipPreviousUpdate: Bool) {
|
||||
runForNumberOfCycles(Int32(cycles))
|
||||
}
|
||||
|
||||
func runForNumberOfCycles(_ numberOfCycles: Int32) {
|
||||
bestEffortLock.lock()
|
||||
if let bestEffortUpdater = bestEffortUpdater {
|
||||
bestEffortLock.unlock()
|
||||
let cyclesToRunFor = min(numberOfCycles, Int32(bestEffortUpdater.clockRate / 10))
|
||||
if actionLock.try() {
|
||||
self.machine.runForNumber(ofCycles: cyclesToRunFor)
|
||||
actionLock.unlock()
|
||||
}
|
||||
} else {
|
||||
bestEffortLock.unlock()
|
||||
final func bestEffortUpdater(_ bestEffortUpdater: CSBestEffortUpdater!, runForInterval duration: TimeInterval, didSkipPreviousUpdate: Bool) {
|
||||
if actionLock.try() {
|
||||
self.machine.run(forInterval: duration)
|
||||
actionLock.unlock()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -14,10 +14,6 @@
|
||||
#import "CSStaticAnalyser.h"
|
||||
|
||||
@class CSMachine;
|
||||
@protocol CSMachineDelegate
|
||||
- (void)machineDidChangeClockRate:(CSMachine *)machine;
|
||||
- (void)machineDidChangeClockIsUnlimited:(CSMachine *)machine;
|
||||
@end
|
||||
|
||||
// Deliberately low; to ensure CSMachine has been declared as an @class already.
|
||||
#import "CSAtari2600.h"
|
||||
@ -33,7 +29,7 @@
|
||||
*/
|
||||
- (instancetype)initWithAnalyser:(CSStaticAnalyser *)result NS_DESIGNATED_INITIALIZER;
|
||||
|
||||
- (void)runForNumberOfCycles:(int)numberOfCycles;
|
||||
- (void)runForInterval:(NSTimeInterval)interval;
|
||||
|
||||
- (float)idealSamplingRateFromRange:(NSRange)range;
|
||||
- (void)setAudioSamplingRate:(float)samplingRate bufferSize:(NSUInteger)bufferSize;
|
||||
@ -46,7 +42,6 @@
|
||||
|
||||
@property (nonatomic, strong) CSAudioQueue *audioQueue;
|
||||
@property (nonatomic, readonly) CSOpenGLView *view;
|
||||
@property (nonatomic, weak) id<CSMachineDelegate> delegate;
|
||||
|
||||
@property (nonatomic, readonly) double clockRate;
|
||||
@property (nonatomic, readonly) BOOL clockIsUnlimited;
|
||||
|
@ -25,8 +25,6 @@
|
||||
|
||||
@interface CSMachine() <CSFastLoading>
|
||||
- (void)speaker:(Outputs::Speaker::Speaker *)speaker didCompleteSamples:(const int16_t *)samples length:(int)length;
|
||||
- (void)machineDidChangeClockRate;
|
||||
- (void)machineDidChangeClockIsUnlimited;
|
||||
@end
|
||||
|
||||
struct LockProtectedDelegate {
|
||||
@ -44,22 +42,8 @@ struct SpeakerDelegate: public Outputs::Speaker::Speaker::Delegate, public LockP
|
||||
}
|
||||
};
|
||||
|
||||
struct MachineDelegate: CRTMachine::Machine::Delegate, public LockProtectedDelegate {
|
||||
void machine_did_change_clock_rate(CRTMachine::Machine *sender) {
|
||||
[machineAccessLock lock];
|
||||
[machine machineDidChangeClockRate];
|
||||
[machineAccessLock unlock];
|
||||
}
|
||||
void machine_did_change_clock_is_unlimited(CRTMachine::Machine *sender) {
|
||||
[machineAccessLock lock];
|
||||
[machine machineDidChangeClockIsUnlimited];
|
||||
[machineAccessLock unlock];
|
||||
}
|
||||
};
|
||||
|
||||
@implementation CSMachine {
|
||||
SpeakerDelegate _speakerDelegate;
|
||||
MachineDelegate _machineDelegate;
|
||||
NSLock *_delegateMachineAccessLock;
|
||||
|
||||
CSStaticAnalyser *_analyser;
|
||||
@ -77,12 +61,8 @@ struct MachineDelegate: CRTMachine::Machine::Delegate, public LockProtectedDeleg
|
||||
|
||||
_delegateMachineAccessLock = [[NSLock alloc] init];
|
||||
|
||||
_machineDelegate.machine = self;
|
||||
_speakerDelegate.machine = self;
|
||||
_machineDelegate.machineAccessLock = _delegateMachineAccessLock;
|
||||
_speakerDelegate.machineAccessLock = _delegateMachineAccessLock;
|
||||
|
||||
_machine->crt_machine()->set_delegate(&_machineDelegate);
|
||||
}
|
||||
return self;
|
||||
}
|
||||
@ -91,14 +71,6 @@ struct MachineDelegate: CRTMachine::Machine::Delegate, public LockProtectedDeleg
|
||||
[self.audioQueue enqueueAudioBuffer:samples numberOfSamples:(unsigned int)length];
|
||||
}
|
||||
|
||||
- (void)machineDidChangeClockRate {
|
||||
[self.delegate machineDidChangeClockRate:self];
|
||||
}
|
||||
|
||||
- (void)machineDidChangeClockIsUnlimited {
|
||||
[self.delegate machineDidChangeClockIsUnlimited:self];
|
||||
}
|
||||
|
||||
- (void)dealloc {
|
||||
// The two delegate's references to this machine are nilled out here because close_output may result
|
||||
// in a data flush, which might cause an audio callback, which could cause the audio queue to decide
|
||||
@ -107,7 +79,6 @@ struct MachineDelegate: CRTMachine::Machine::Delegate, public LockProtectedDeleg
|
||||
// They are nilled inside an explicit lock because that allows the delegates to protect their entire
|
||||
// call into the machine, not just the pointer access.
|
||||
[_delegateMachineAccessLock lock];
|
||||
_machineDelegate.machine = nil;
|
||||
_speakerDelegate.machine = nil;
|
||||
[_delegateMachineAccessLock unlock];
|
||||
|
||||
@ -146,9 +117,9 @@ struct MachineDelegate: CRTMachine::Machine::Delegate, public LockProtectedDeleg
|
||||
}
|
||||
}
|
||||
|
||||
- (void)runForNumberOfCycles:(int)numberOfCycles {
|
||||
- (void)runForInterval:(NSTimeInterval)interval {
|
||||
@synchronized(self) {
|
||||
_machine->crt_machine()->run_for(Cycles(numberOfCycles));
|
||||
_machine->crt_machine()->run_for(interval);
|
||||
}
|
||||
}
|
||||
|
||||
@ -175,10 +146,6 @@ struct MachineDelegate: CRTMachine::Machine::Delegate, public LockProtectedDeleg
|
||||
return _machine->crt_machine()->get_clock_rate();
|
||||
}
|
||||
|
||||
- (BOOL)clockIsUnlimited {
|
||||
return _machine->crt_machine()->get_clock_is_unlimited() ? YES : NO;
|
||||
}
|
||||
|
||||
- (void)paste:(NSString *)paste {
|
||||
KeyboardMachine::Machine *keyboardMachine = _machine->keyboard_machine();
|
||||
if(keyboardMachine)
|
||||
|
@ -13,15 +13,13 @@
|
||||
|
||||
@protocol CSBestEffortUpdaterDelegate <NSObject>
|
||||
|
||||
- (void)bestEffortUpdater:(CSBestEffortUpdater *)bestEffortUpdater runForCycles:(NSUInteger)cycles didSkipPreviousUpdate:(BOOL)didSkipPreviousUpdate;
|
||||
- (void)bestEffortUpdater:(CSBestEffortUpdater *)bestEffortUpdater runForInterval:(NSTimeInterval)interval didSkipPreviousUpdate:(BOOL)didSkipPreviousUpdate;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@interface CSBestEffortUpdater : NSObject
|
||||
|
||||
@property (nonatomic, assign) double clockRate;
|
||||
@property (nonatomic, assign) BOOL runAsUnlimited;
|
||||
@property (nonatomic, weak) id<CSBestEffortUpdaterDelegate> delegate;
|
||||
|
||||
- (void)update;
|
||||
|
@ -14,12 +14,12 @@ struct UpdaterDelegate: public Concurrency::BestEffortUpdater::Delegate {
|
||||
__weak id<CSBestEffortUpdaterDelegate> delegate;
|
||||
NSLock *delegateLock;
|
||||
|
||||
void update(Concurrency::BestEffortUpdater *updater, int cycles, bool did_skip_previous_update) {
|
||||
void update(Concurrency::BestEffortUpdater *updater, Time::Seconds cycles, bool did_skip_previous_update) {
|
||||
[delegateLock lock];
|
||||
__weak id<CSBestEffortUpdaterDelegate> delegateCopy = delegate;
|
||||
[delegateLock unlock];
|
||||
|
||||
[delegateCopy bestEffortUpdater:nil runForCycles:(NSUInteger)cycles didSkipPreviousUpdate:did_skip_previous_update];
|
||||
[delegateCopy bestEffortUpdater:nil runForInterval:(NSTimeInterval)cycles didSkipPreviousUpdate:did_skip_previous_update];
|
||||
}
|
||||
};
|
||||
|
||||
@ -51,11 +51,6 @@ struct UpdaterDelegate: public Concurrency::BestEffortUpdater::Delegate {
|
||||
_updater.flush();
|
||||
}
|
||||
|
||||
- (void)setClockRate:(double)clockRate {
|
||||
_clockRate = clockRate;
|
||||
_updater.set_clock_rate(clockRate);
|
||||
}
|
||||
|
||||
- (void)setDelegate:(id<CSBestEffortUpdaterDelegate>)delegate {
|
||||
[_delegateLock lock];
|
||||
_updaterDelegate.delegate = delegate;
|
||||
|
Loading…
x
Reference in New Issue
Block a user