We now have a new way to make a lazy variable. It is described in swift-evolution/proposals/0258-property-wrappers.md:
@propertyWrapper
enum Lazy<Value> {
case uninitialized(() -> Value)
case initialized(Value)
init(wrappedValue: @autoclosure @escaping () -> Value) {
self = .uninitialized(wrappedValue)
}
var wrappedValue: Value {
mutating get {
switch self {
case .uninitialized(let initializer):
let value = initializer()
self = .initialized(value)
return value
case .initialized(let value):
return value
}
}
set {
self = .initialized(newValue)
}
}
}
Is it a thread safe implementation? If not, how to reproduce non thread safe behavior?
I had the same question, so I tested it out by writing a small test that uses this property wrapper on a property in a class, and then try to print out the value (time since epoch) async (10000 times) and it blew up with a SIGABRT on the 'return value' line inside the getter of wrappedValue.
I also tried just 'getting' the value without printing, and I had the same issue.
So I would have to say: no, it is not thread safe.
EDIT: I'd like to add that I did the same test on https://www.onswiftwings.com/posts/atomic-property-wrapper/ and that one is indeed thread safe, so you could use that as a base to make your own 'Lazy' that is thread safe.