Last active
July 13, 2018 15:25
-
-
Save a-voronov/85936fb6d491fb4b5625fd1941959639 to your computer and use it in GitHub Desktop.
Concurrent Reads, Blocking Write
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class ReadWriteQueue { | |
private let specificKey = DispatchSpecificKey<String>() | |
private let queue: DispatchQueue | |
private var isAlreadyInQueue: Bool { | |
return DispatchQueue.getSpecific(key: specificKey) == queue.label | |
} | |
init(label: String = "read-write.queue") { | |
queue = DispatchQueue(label: label, attributes: .concurrent) | |
queue.setSpecific(key: specificKey, value: label) | |
} | |
deinit { | |
queue.setSpecific(key: specificKey, value: nil) | |
} | |
// solving readers-writers problem: any amount of readers can access data at a time, but only one writer is allowed at a time | |
// - reads are executed concurrently on executing queue, but are executed synchronously on a calling queue | |
// - write blocks executing queue, but is executed asynchronously on a calling queue so it doesn't have to wait | |
// note: | |
// it's fine to have async write, and sync reads, because write blocks queue and reads are executed synchronously; | |
// so if we want ro read after writing, we'll still be waiting (reads are sync) for write to finish and allow reads to execute; | |
func write(_ work: @escaping () -> Void) { | |
if isAlreadyInQueue { | |
work() | |
} else { | |
queue.async(flags: .barrier, execute: work) | |
} | |
} | |
// if we're already executing inside queue, then no need to add task there synchronosuly since it can lead to a deadlock | |
func read<T>(_ work: () throws -> T) rethrows -> T { | |
if isAlreadyInQueue { | |
return try work() | |
} else { | |
return try queue.sync(execute: work) | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment