AlphaModder
AlphaModder

Reputation: 3386

What's the right way to have a thread-safe lazy-initialized possibly mutable value in Rust?

I have a struct that contains a field that is rather expensive to initialize, so I want to be able to do so lazily. However, this may be necessary in a method that takes &self. The field also needs to be able to modified once it is initialized, but this will only occur in methods that take &mut self.

What is the correct (as in idiomatic, as well as in thread-safe) way to do this in Rust? It seems to me that it would be trivial with either of the two constraints:

However, I'm not quite sure what to do with both in place. RwLock seems relevant, but it appears that there is considerable trickiness to thread-safe lazy initialization given what I've seen of lazy-init's source, so I am hesitant to roll my own solution based on it.

Upvotes: 4

Views: 2092

Answers (1)

Matthieu M.
Matthieu M.

Reputation: 300149

The simplest solution is RwLock<Option<T>>.

However, I'm not quite sure what to do with both in place. RwLock seems relevant, but it appears that there is considerable trickiness to thread-safe lazy initialization given what I've seen of lazy-init's source, so I am hesitant to roll my own solution based on it.

lazy-init uses tricky code because it guarantees lock-free access after creation. Lock-free is always a bit trickier.

Note that in Rust it's easy to tell whether something is tricky or not: tricky means using an unsafe block. Since you can use RwLock<Option<T>> without any unsafe block there is nothing for you to worry about.


A variant to RwLock<Option<T>> may be necessary if you want to capture a closure for initialization once, rather than have to pass it at each potential initialization call-site.

In this case, you'll need something like RwLock<SimpleLazy<T>> where:

enum SimpleLazy<T> {
    Initialized(T),
    Uninitialized(Box<FnOnce() -> T>),
}

You don't have to worry about making SimpleLazy<T> Sync as RwLock will take care of that for you.

Upvotes: 5

Related Questions