Created
October 20, 2019 21:34
-
-
Save Alkenso/74962054a64cab0c635fbe1f54dfa4f5 to your computer and use it in GitHub Desktop.
Swift atomic property using @propertyWrapper
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
| // 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