Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is Property Wrapper @Lazy variable thread safe?

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?

like image 308
iWheelBuy Avatar asked Oct 29 '19 06:10

iWheelBuy


People also ask

Are Lazy properties thread safe?

The Lazy<T> instance is not thread safe; if the instance is accessed from multiple threads, its behavior is undefined. Use this mode only when high performance is crucial and the Lazy<T> instance is guaranteed never to be initialized from more than one thread.

Is Lazy var thread safe Swift?

Another problem is that lazy var is not thread-safe which means the closure can get executed multiple times due to accesses from different threads.

What is Property wrappers in Swift?

Property Wrappers in Swift allow you to extract common logic in a distinct wrapper object. This new technique appeared at WWDC 2019 and first became available in Swift 5. It's a neat addition to the Swift library that allows removing much boilerplate code, which we probably all have written in our projects.

Why Lazy Cannot be used on a let?

You can't make it lazy let because lazy properties must always be variables. Because the actual value is created by evaluation, you need to declare its data type up front. In the case of the code above, that means declaring the property as Int .


1 Answers

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.

like image 176
Tim Avatar answered Sep 28 '22 06:09

Tim