Skip to content

Instantly share code, notes, and snippets.

@KaQuMiQ
Created March 1, 2021 10:18
Show Gist options
  • Select an option

  • Save KaQuMiQ/e0e2bbc100b68bb54a3ebd542a04d51f to your computer and use it in GitHub Desktop.

Select an option

Save KaQuMiQ/e0e2bbc100b68bb54a3ebd542a04d51f to your computer and use it in GitHub Desktop.
import class Foundation.NSRecursiveLock
@dynamicMemberLookup @propertyWrapper
public final class Synchronized<Value> {
public var wrappedValue: Value {
get {
lock()
defer { unlock() }
return value
}
set {
lock()
value = newValue
unlock()
}
}
private var value: Value
private let lock: () -> Void
private let unlock: () -> Void
public convenience init(_ value: Value) {
let recursiveLock = NSRecursiveLock()
self.init(
value,
lock: recursiveLock.lock,
unlock: recursiveLock.unlock
)
}
public init(
_ value: Value,
lock: @escaping () -> Void,
unlock: @escaping () -> Void
) {
self.value = value
self.lock = lock
self.unlock = unlock
}
public subscript<T>(dynamicMember keyPath: KeyPath<Value, T>) -> T {
get {
lock()
defer { unlock() }
return value[keyPath: keyPath]
}
}
public subscript<T>(dynamicMember keyPath: WritableKeyPath<Value, T>) -> T {
get {
lock()
defer { unlock() }
return value[keyPath: keyPath]
}
set {
lock()
value[keyPath: keyPath] = newValue
unlock()
}
}
public subscript<T: AnyObject>(dynamicMember keyPath: ReferenceWritableKeyPath<Value, T>) -> T {
get {
lock()
defer { unlock() }
return value[keyPath: keyPath]
}
set {
lock()
value[keyPath: keyPath] = newValue
unlock()
}
}
public func synchronizedAccess(_ closure: (inout Value) -> Void) {
lock()
closure(&value)
unlock()
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment