This is a tracking issue for the unstable static_mutex, static_condvar, and static_rwlock features in the standard library. Each of these represents a separate StaticFoo type (next to the type Foo) to provide a synchronization primitive that can be constructed in a static context. This unfortunately has a few drawbacks:
StaticMutex does not have a type parameter for the data that it protects (unlike Mutex<T>)Ideally all of these types would be removed in favor of being able to construct a Mutex<T> statically. This can almost be done with const fn, but the implementation of each of these primitives currently has an internal Box which can't be constructed in a static context. A solution should probably be devised along the lines of:
Box at runtime and just a plain address when inlined into a static. It also wouldn't have a destructor for the purposes of checking whether statics have destructors.box operator could be allowed in a const fn context perhaps. Instead of allocating memory on the heap it could instead "allocate" memory in the data section of an executable at compile time. The destructor would end up being ignored and never run somehow, possibly.cc @eddyb
Alternatively we could put some code into .ctors for each static Mutex.dtors).
The Box itself is very unfortunate, but a proper system is quite complex, and requiring Mutex<T> & friends to be in a stable location is not backwards-compatible.
Developing a proper system for types which are "immovable after address was first observed" and using it in, e.g. sync::stable::Mutex<T> (replacing StaticMutex), might just work.
I wrote down an idea for such a system a few months ago, in an internals.rust-lang.org post, might still be relevant.
Definitely with @eddyb for the long term, but in the short term would be nice if Static* and Once could get type parameters.
馃敂 This issue is now entering its cycle long final comment period 馃敂
The libs team is thinking of deprecating these APIs in favor of the lazy_static! crate on crates.io, as that should suffice for now for statically allocated synchronization primitives.
The parking_lot crate has implementations of Mutex, Condvar and RwLock that can be statically constructed and do not require any drop logic.
@Amanieu I prefer that to any sort of scheme which magically makes Box work or handles types which can't be moved.
I had the impression that you couldn't actually build reliable abstractions while allowing moves of the metadata involved and I'm glad to be wrong :smile:.
The libs team discussed this during triage yesterday and the decision was to deprecate. This seems easily-replaceable enough with the lazy-static crate, @Amanieu's crate seems quite nice, and one day we'd love for Mutex::new to "Just Work" in a static context. With all that in mind it seems like we're not buying much keeping these unstable, so we're deprecating.
Migration path from StaticMutex to using a Mutex plus the lazy_static crate:
static LOCK: StaticMutex = MUTEX_INIT;
Replace it with:
lazy_static! {
pub static ref LOCK: Mutex<()> = Mutex::new(());
}
If you鈥檙e protecting data with the mutex, then you can use something better than (). (I wasn鈥檛, I was just preventing a handful of tests from running in parallel because of a global static used solely for testing purposes.)
lazy_static! {
pub static ref LOCK: Mutex<()> = Mutex::new(());
}
Doesn鈥檛 this have more runtime cost? It has two synchronization points (lazy_static! uses Once internally, and Mutex synchronizes again).
The Once is basically free once the object has been constructed. It's just a load, a compare and a branch.
The Pin stuff for futures isn't sufficient for this, is it? Certainly it wouldn't be backwards compatible IIUC.
Most helpful comment
The libs team discussed this during triage yesterday and the decision was to deprecate. This seems easily-replaceable enough with the
lazy-staticcrate, @Amanieu's crate seems quite nice, and one day we'd love forMutex::newto "Just Work" in a static context. With all that in mind it seems like we're not buying much keeping these unstable, so we're deprecating.