1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-11-23 03:32:32 +00:00

Ensures safe machine release upon window closure.

This commit is contained in:
Thomas Harte 2017-09-30 20:07:04 -04:00
parent 326857a84d
commit f86729c4ac
3 changed files with 30 additions and 14 deletions

View File

@ -95,9 +95,16 @@ class MachineDocument:
}
override func close() {
bestEffortUpdater.flush()
optionsPanel?.setIsVisible(false)
optionsPanel = nil
openGLView.delegate = nil
bestEffortUpdater.delegate = nil
bestEffortUpdater = nil
actionLock.lock()
drawLock.lock()
machine = nil
openGLView.invalidate()
openGLView.openGLContext!.makeCurrentContext()
actionLock.unlock()

View File

@ -22,7 +22,7 @@
@property (nonatomic, assign) double clockRate;
@property (nonatomic, assign) BOOL runAsUnlimited;
@property (nonatomic, weak) id<CSBestEffortUpdaterDelegate> delegate;
@property (atomic, weak) id<CSBestEffortUpdaterDelegate> delegate;
- (void)update;
- (void)flush;

View File

@ -20,6 +20,7 @@
NSTimeInterval _previousTimeInterval;
NSTimeInterval _cyclesError;
BOOL _hasSkipped;
id<CSBestEffortUpdaterDelegate> _delegate;
}
- (instancetype)init
@ -35,15 +36,12 @@
return self;
}
- (void)update
{
- (void)update {
// Always post an -openGLView:didUpdateToTime: if a previous one isn't still ongoing. This is the hook upon which the substantial processing occurs.
if(!atomic_flag_test_and_set(&_updateIsOngoing))
{
if(!atomic_flag_test_and_set(&_updateIsOngoing)) {
dispatch_async(_serialDispatchQueue, ^{
NSTimeInterval timeInterval = [NSDate timeIntervalSinceReferenceDate];
if(_previousTimeInterval > DBL_EPSILON && timeInterval > _previousTimeInterval)
{
if(_previousTimeInterval > DBL_EPSILON && timeInterval > _previousTimeInterval) {
NSTimeInterval timeToRunFor = timeInterval - _previousTimeInterval;
double cyclesToRunFor = timeToRunFor * self.clockRate + _cyclesError;
@ -52,24 +50,35 @@
// treat 'unlimited' as running at a factor of 10
if(self.runAsUnlimited) integerCyclesToRunFor *= 10;
[self.delegate bestEffortUpdater:self runForCycles:integerCyclesToRunFor didSkipPreviousUpdate:_hasSkipped];
[_delegate bestEffortUpdater:self runForCycles:integerCyclesToRunFor didSkipPreviousUpdate:_hasSkipped];
}
_previousTimeInterval = timeInterval;
_hasSkipped = NO;
atomic_flag_clear(&_updateIsOngoing);
});
}
else
{
} else {
dispatch_async(_serialDispatchQueue, ^{
_hasSkipped = YES;
});
}
}
- (void)flush
{
- (void)flush {
dispatch_sync(_serialDispatchQueue, ^{});
}
- (void)setDelegate:(id<CSBestEffortUpdaterDelegate>)delegate {
dispatch_sync(_serialDispatchQueue, ^{
_delegate = delegate;
});
}
- (id<CSBestEffortUpdaterDelegate>)delegate {
__block id<CSBestEffortUpdaterDelegate> delegate;
dispatch_sync(_serialDispatchQueue, ^{
delegate = _delegate;
});
return delegate;
}
@end