once_cell
is being gradually incorporated into std
, so it'll eventually be possible in stable without crates. This works on nightly today:
use std::lazy::SyncLazy;
use std::sync::Mutex;
static LAZY: SyncLazy<Mutex<()>> = SyncLazy::new(Mutex::default);
However, since SyncLazy
is essentially a mutex already, putting a sync::Mutex
inside it does seem a bit overkill. parking_lot
's Mutex
doesn't have this problem since you can just make it a regular (i.e., non-lazy) static
.
I think Once::call_once_force
is okay in scenarios like this. It looks like it has a wait queue so it's not just a spinlock. It might be nice if there was another way in the standard library but I wouldn't stress about it. The calling code is ugly, though -- I'd try to wrap that up in a nice wrapper so I could just call SYNC.with_lock(|| whatever)
.
However, you might want to consider what it is you're actually synchronizing access to. In the original example you synchronize access to a local variable, something that should probably be done with a plain Mutex
instead. If what you're doing in your real code resembles that, there might be something to the idea that you're abusing Once
.