Last active
August 23, 2020 19:18
-
-
Save suhitp/79720cc53c32351eb404e5d3c5030596 to your computer and use it in GitHub Desktop.
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
// MARK: Lock Protocol | |
protocol Lock: AnyObject { | |
/// locks the resource to execute action | |
func lock() | |
/// unlocks the resource | |
func unlock() | |
} | |
extension Lock { | |
/// Executes a closure returning a value while acquiring the lock. | |
/// - Parameter closure: The closure to run. | |
/// - Returns: The value the closure generated. | |
func readAction<T>(_ closure: () -> T) -> T { | |
lock(); defer { unlock() } | |
return closure() | |
} | |
/// Execute a closure while acquiring the lock. | |
/// - Parameter closure: The closure to run. | |
func writeAction(_ closure: () -> Void) { | |
lock(); defer { unlock() } | |
closure() | |
} | |
} | |
final class ThreadSafeLock: Lock { | |
private lazy var unfairLock = os_unfair_lock_s() | |
private lazy var _lock = NSLock() | |
func lock() { | |
if #available(iOS 10.0, *) { | |
os_unfair_lock_lock(&unfairLock) | |
} else { | |
_lock.lock() | |
} | |
} | |
func unlock() { | |
if #available(iOS 10.0, *) { | |
os_unfair_lock_unlock(&unfairLock) | |
} else { | |
_lock.unlock() | |
} | |
} | |
} | |
@propertyWrapper | |
final class ThreadSafeProperty<T> { | |
private var value: T | |
private let lock = ThreadSafeLock() | |
init(wrappedValue: T) { | |
self.value = wrappedValue | |
} | |
/// The contained value. Unsafe for anything more than direct read or write. | |
var wrappedValue: T { | |
get { lock.readAction { value } } | |
set { lock.writeAction { value = newValue } } | |
} | |
var projectedValue: ThreadSafeProperty<T> { self } | |
/// Synchronously read or transform the contained value. | |
/// - Parameter closure: The closure to execute. | |
/// - Returns: The return value of the closure passed. | |
func read<U>(_ closure: (T) -> U) -> U { | |
return lock.readAction { closure(self.value) } | |
} | |
/// Synchronously modify the protected value. | |
/// - Parameter closure: The closure to execute. | |
/// - Returns: The modified value. | |
func write<U>(_ closure: (inout T) -> U) -> Void { | |
lock.readAction { closure(&self.value) } | |
} | |
} |
Author
suhitp
commented
Jun 7, 2020
•
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment