From 7d75e864b1e566f78b53c63f21ac9f296b65d17d Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Sun, 18 Feb 2018 22:09:03 -0500 Subject: [PATCH] Ensures thread safety of usages of `bestEffortLock`. --- .../Documents/MachineDocument.swift | 20 ++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/OSBindings/Mac/Clock Signal/Documents/MachineDocument.swift b/OSBindings/Mac/Clock Signal/Documents/MachineDocument.swift index 8fbdad7fc..34ea26be3 100644 --- a/OSBindings/Mac/Clock Signal/Documents/MachineDocument.swift +++ b/OSBindings/Mac/Clock Signal/Documents/MachineDocument.swift @@ -18,8 +18,10 @@ class MachineDocument: CSBestEffortUpdaterDelegate, CSAudioQueueDelegate { - lazy var actionLock = NSLock() - lazy var drawLock = NSLock() + fileprivate let actionLock = NSLock() + fileprivate let drawLock = NSLock() + fileprivate let bestEffortLock = NSLock() + var machine: CSMachine! var name: String! { get { @@ -77,7 +79,9 @@ class MachineDocument: } func machineDidChangeClockIsUnlimited(_ machine: CSMachine!) { + bestEffortLock.lock() self.bestEffortUpdater?.runAsUnlimited = machine.clockIsUnlimited + bestEffortLock.unlock() } fileprivate func setupClockRate() { @@ -91,20 +95,24 @@ class MachineDocument: self.machine.setAudioSamplingRate(selectedSamplingRate, bufferSize:audioQueue.preferredBufferSize) } + bestEffortLock.lock() self.bestEffortUpdater?.clockRate = self.machine.clockRate + bestEffortLock.unlock() } override func close() { optionsPanel?.setIsVisible(false) optionsPanel = nil - openGLView.delegate = nil + bestEffortLock.lock() bestEffortUpdater!.delegate = nil bestEffortUpdater = nil + bestEffortLock.unlock() actionLock.lock() drawLock.lock() machine = nil + openGLView.delegate = nil openGLView.invalidate() actionLock.unlock() drawLock.unlock() @@ -148,6 +156,7 @@ class MachineDocument: } func runForNumberOfCycles(_ numberOfCycles: Int32) { + bestEffortLock.lock() if let bestEffortUpdater = bestEffortUpdater { let cyclesToRunFor = min(numberOfCycles, Int32(bestEffortUpdater.clockRate / 10)) if actionLock.try() { @@ -155,15 +164,19 @@ class MachineDocument: actionLock.unlock() } } + bestEffortLock.unlock() } // MARK: CSAudioQueueDelegate final func audioQueueIsRunningDry(_ audioQueue: CSAudioQueue) { + bestEffortLock.lock() bestEffortUpdater?.update() + bestEffortLock.unlock() } // MARK: CSOpenGLViewDelegate final func openGLView(_ view: CSOpenGLView, drawViewOnlyIfDirty onlyIfDirty: Bool) { + bestEffortLock.lock() if let bestEffortUpdater = bestEffortUpdater { bestEffortUpdater.update() if drawLock.try() { @@ -171,6 +184,7 @@ class MachineDocument: drawLock.unlock() } } + bestEffortLock.unlock() } final func openGLView(_ view: CSOpenGLView, didReceiveFileAt URL: URL) {