Created
February 8, 2020 21:16
-
-
Save jeffery812/29eb493edbfc404ca3016e3485c1f703 to your computer and use it in GitHub Desktop.
This file contains 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
// https://www.vadimbulavin.com/swift-atomic-properties-with-property-wrappers/ | |
/* | |
Although get and set are individually atomic, the combination of both is not. | |
Incrementing x is not atomic, since it first calls get and then set: | |
*/ | |
@propertyWrapper | |
struct Atomic<Value> { | |
private let queue = DispatchQueue(label: "com.vadimbulavin.atomic") | |
private var value: Value | |
init(wrappedValue: Value) { | |
self.value = wrappedValue | |
} | |
var wrappedValue: Value { | |
get { | |
return queue.sync { value } | |
} | |
set { | |
queue.sync { value = newValue } | |
} | |
} | |
func mutate(_ mutation: (inout Value) -> Void) { | |
queue.sync { mutation(&value) } | |
} | |
} | |
struct MyStruct { | |
@Atomic var x = 0 | |
} | |
// Verison 2 | |
/* | |
When we update a value in a collection (Array, Set and Dictionary), | |
both get and set are called. Make sure to use the mutate() method in such cases: | |
*/ | |
@propertyWrapper | |
class Atomic<T> { | |
private let queue = DispatchQueue(label: "com.vadimbulavin.atomic") | |
var projectedValue: Atomic<T> { return self } | |
var value: T | |
init(wrappedValue: T) { | |
self.value = wrappedValue | |
} | |
var wrappedValue: T { | |
get { | |
print("wrappedValue get \(value)") | |
return queue.sync { value } | |
} | |
set { | |
print("wrappedValue set \(newValue) -> \(value)") | |
queue.sync { value = newValue } | |
} | |
} | |
func mutate(_ mutation: (inout T) -> Void) { | |
queue.sync { mutation(&value) } | |
} | |
func help() { | |
print("help") | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment