Skip to content

Instantly share code, notes, and snippets.

@Alkenso
Created October 20, 2019 21:34
Show Gist options
  • Select an option

  • Save Alkenso/74962054a64cab0c635fbe1f54dfa4f5 to your computer and use it in GitHub Desktop.

Select an option

Save Alkenso/74962054a64cab0c635fbe1f54dfa4f5 to your computer and use it in GitHub Desktop.
Swift atomic property using @propertyWrapper
// Requires Swift 5.1 (Xcode 11.1+).
//
// Using pthread_rw_lock allows to minimize system resources
// and prevent creation of DispatchQueue per each @Atomic property.
//
@propertyWrapper
final class Atomic<Value> {
var value: Value
var lock = pthread_rwlock_t()
init(wrappedValue: Value) {
self.value = wrappedValue
}
var wrappedValue: Value {
get {
pthread_rwlock_rdlock(&lock)
defer { pthread_rwlock_unlock(&lock) }
return value
}
set {
pthread_rwlock_wrlock(&lock)
defer { pthread_rwlock_unlock(&lock) }
value = newValue
}
}
func mutate(_ transform: (inout Value) -> Void) {
pthread_rwlock_wrlock(&lock)
defer { pthread_rwlock_unlock(&lock) }
transform(&value)
}
}
// Usage example
class A {
@Atomic var text: String = ""
func foo() {
for i in 1..<10000 {
DispatchQueue.global().async {
self.text = String(i)
}
}
}
func bar() {
// Assume you want to change value atomically dealing with its previous value
_text.mutate { $0 += "-bar" }
}
}
// main
let a = A()
a.foo()
a.bar()
RunLoop.main.run()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment