3 ms·
> why is the C mutex API structured in a way that is hard to use and trivial to misuse, requiring elaborate comments or even static analysis to get right? ....
by wahern 5y ago
> why is the C mutex API structured in a way that is hard to use and trivial to misuse, requiring elaborate comments or even static analysis to get right? .... There are important language features missing from C (and C++) that make it impossible to implement a Rust-style mutex API with the same guarantees
The simple answer is that the C11 Threads API was designed so that it could be trivially implemented using either POSIX or Windows threading primitives. One annoying consequence is that C11 mutexes do not support static initialization, unlike POSIX mutexes. (AFAIU Windows does provide some primitives to accomplish this, but not the standard mutexes it was presumed the C11 Threads would be mapped.)
In principle C11 could have specified a safer API along with any necessary semantic changes. It had to do this to some degree with atomics. Heck, it could have even introduced some narrowly scoped dependent typing, which is basically what some of the recent proposals regarding arrays do. But AFAIU nobody even looked in that direction as the focus was on finding a common, simple subset of POSIX and Windows API facilities.
- ReactiveJelly 5y agoStatic initialization? Does that mean initializing the mutex before main?
- nyanpasu64 5y agoThere are two types of static initialization (initialization before main): constant and running code. Only C++ supports running code before main to initialize static-lifetime variables, and this feature is regarded as dangerous due to the static initialization order fiasco (referencing non-constant-initialized globals defined in other TUs will randomly see either all zeros or the initialized value, depending on the linking order of TUs). (C on Unix has a platform-specific __attribute__ ((constructor)) to do the same thing, but it's not standardized). Standard C and Rust don't allow running code before main to statically initialize mutexes. Rust mutexes cannot be statically const-initialized either. So if you want a global mutex, you have to use a once_cell::sync::Lazy or lazy_static! to construct the contents on first read (adding an extra branch on every access). On the other hand, parking_lot offers a statically constructible (const-initializable) Mutex independent of OS synchronization primitives (https://docs.rs/parking_lot/latest/parking_lot/type.Mutex.html https://docs.rs/parking_lot/latest/parking_lot/type.Mutex.ht...) which doesn't require a OnceCell/Lazy/lazy_static around it.