1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-08-16 16:28:59 +00:00

Ensures thread safety of usages of bestEffortLock.

This commit is contained in:
Thomas Harte 2018-02-18 22:09:03 -05:00
parent a005dabbe3
commit 7d75e864b1

View File

@ -18,8 +18,10 @@ class MachineDocument:
CSBestEffortUpdaterDelegate, CSBestEffortUpdaterDelegate,
CSAudioQueueDelegate CSAudioQueueDelegate
{ {
lazy var actionLock = NSLock() fileprivate let actionLock = NSLock()
lazy var drawLock = NSLock() fileprivate let drawLock = NSLock()
fileprivate let bestEffortLock = NSLock()
var machine: CSMachine! var machine: CSMachine!
var name: String! { var name: String! {
get { get {
@ -77,7 +79,9 @@ class MachineDocument:
} }
func machineDidChangeClockIsUnlimited(_ machine: CSMachine!) { func machineDidChangeClockIsUnlimited(_ machine: CSMachine!) {
bestEffortLock.lock()
self.bestEffortUpdater?.runAsUnlimited = machine.clockIsUnlimited self.bestEffortUpdater?.runAsUnlimited = machine.clockIsUnlimited
bestEffortLock.unlock()
} }
fileprivate func setupClockRate() { fileprivate func setupClockRate() {
@ -91,20 +95,24 @@ class MachineDocument:
self.machine.setAudioSamplingRate(selectedSamplingRate, bufferSize:audioQueue.preferredBufferSize) self.machine.setAudioSamplingRate(selectedSamplingRate, bufferSize:audioQueue.preferredBufferSize)
} }
bestEffortLock.lock()
self.bestEffortUpdater?.clockRate = self.machine.clockRate self.bestEffortUpdater?.clockRate = self.machine.clockRate
bestEffortLock.unlock()
} }
override func close() { override func close() {
optionsPanel?.setIsVisible(false) optionsPanel?.setIsVisible(false)
optionsPanel = nil optionsPanel = nil
openGLView.delegate = nil bestEffortLock.lock()
bestEffortUpdater!.delegate = nil bestEffortUpdater!.delegate = nil
bestEffortUpdater = nil bestEffortUpdater = nil
bestEffortLock.unlock()
actionLock.lock() actionLock.lock()
drawLock.lock() drawLock.lock()
machine = nil machine = nil
openGLView.delegate = nil
openGLView.invalidate() openGLView.invalidate()
actionLock.unlock() actionLock.unlock()
drawLock.unlock() drawLock.unlock()
@ -148,6 +156,7 @@ class MachineDocument:
} }
func runForNumberOfCycles(_ numberOfCycles: Int32) { func runForNumberOfCycles(_ numberOfCycles: Int32) {
bestEffortLock.lock()
if let bestEffortUpdater = bestEffortUpdater { if let bestEffortUpdater = bestEffortUpdater {
let cyclesToRunFor = min(numberOfCycles, Int32(bestEffortUpdater.clockRate / 10)) let cyclesToRunFor = min(numberOfCycles, Int32(bestEffortUpdater.clockRate / 10))
if actionLock.try() { if actionLock.try() {
@ -155,15 +164,19 @@ class MachineDocument:
actionLock.unlock() actionLock.unlock()
} }
} }
bestEffortLock.unlock()
} }
// MARK: CSAudioQueueDelegate // MARK: CSAudioQueueDelegate
final func audioQueueIsRunningDry(_ audioQueue: CSAudioQueue) { final func audioQueueIsRunningDry(_ audioQueue: CSAudioQueue) {
bestEffortLock.lock()
bestEffortUpdater?.update() bestEffortUpdater?.update()
bestEffortLock.unlock()
} }
// MARK: CSOpenGLViewDelegate // MARK: CSOpenGLViewDelegate
final func openGLView(_ view: CSOpenGLView, drawViewOnlyIfDirty onlyIfDirty: Bool) { final func openGLView(_ view: CSOpenGLView, drawViewOnlyIfDirty onlyIfDirty: Bool) {
bestEffortLock.lock()
if let bestEffortUpdater = bestEffortUpdater { if let bestEffortUpdater = bestEffortUpdater {
bestEffortUpdater.update() bestEffortUpdater.update()
if drawLock.try() { if drawLock.try() {
@ -171,6 +184,7 @@ class MachineDocument:
drawLock.unlock() drawLock.unlock()
} }
} }
bestEffortLock.unlock()
} }
final func openGLView(_ view: CSOpenGLView, didReceiveFileAt URL: URL) { final func openGLView(_ view: CSOpenGLView, didReceiveFileAt URL: URL) {