diff --git a/OSBindings/Mac/Clock Signal/Documents/MachineDocument.swift b/OSBindings/Mac/Clock Signal/Documents/MachineDocument.swift index 4949e9989..605db2f06 100644 --- a/OSBindings/Mac/Clock Signal/Documents/MachineDocument.swift +++ b/OSBindings/Mac/Clock Signal/Documents/MachineDocument.swift @@ -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() diff --git a/OSBindings/Mac/Clock Signal/Updater/CSBestEffortUpdater.h b/OSBindings/Mac/Clock Signal/Updater/CSBestEffortUpdater.h index 7130f3636..5bf76a152 100644 --- a/OSBindings/Mac/Clock Signal/Updater/CSBestEffortUpdater.h +++ b/OSBindings/Mac/Clock Signal/Updater/CSBestEffortUpdater.h @@ -22,7 +22,7 @@ @property (nonatomic, assign) double clockRate; @property (nonatomic, assign) BOOL runAsUnlimited; -@property (nonatomic, weak) id delegate; +@property (atomic, weak) id delegate; - (void)update; - (void)flush; diff --git a/OSBindings/Mac/Clock Signal/Updater/CSBestEffortUpdater.m b/OSBindings/Mac/Clock Signal/Updater/CSBestEffortUpdater.m index eeb24c99e..67b44d18c 100644 --- a/OSBindings/Mac/Clock Signal/Updater/CSBestEffortUpdater.m +++ b/OSBindings/Mac/Clock Signal/Updater/CSBestEffortUpdater.m @@ -20,6 +20,7 @@ NSTimeInterval _previousTimeInterval; NSTimeInterval _cyclesError; BOOL _hasSkipped; + id _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)delegate { + dispatch_sync(_serialDispatchQueue, ^{ + _delegate = delegate; + }); +} + +- (id)delegate { + __block id delegate; + dispatch_sync(_serialDispatchQueue, ^{ + delegate = _delegate; + }); + return delegate; +} + @end