Why Rust mutexes look like they do
cliffle.com
cliffle.com
Are you saying this is always wrong? I thought that depended on the use case at hand.
To prevent tearing, you can use a regular mutex (only one reader at a time), or https://en.wikipedia.org/wiki/Readers%E2%80%93writer_lock, which allows multiple concurrent readers, but has more overhead than a regular mutex, and when contention occurs can prioritize either readers or writers. If you don't want readers or writers to block, you can use (for <=64-bit values) atomic reads and writes, (for single writers and readers) triple buffers, or (in general) RCU or hazard pointers.
BUT, for large values (structs) you will end up getting ragged reads if another thread is writing at the same time. And if another thread is not writing at the same time, what's the harm in locking for reads? Modern mutexes lock fast if there's no contention.
BUT ALSO, many operations are actually a read, followed by a related write. If you don't lock on reads, it's easy to accidentally compose multiple small, correct functions, into a large, incorrect function.
I've done some experimenting here, and I think it is possible to add a borrow checker to a C or C++ -like language, like the author hints. It couldn't be like Rust's borrow checker, it would just need to be a borrow checker that operates on a "per region" basis, where everything inside the mutex is one region and everything outside is another.
I wrote a little bit about this idea for the Vale language in [0] and then realized shortly afterward that the idea can be used to add fearless concurrency to any existing language.
[0]: https://verdagon.dev/blog/seamless-fearless-structured-concu...
Then they can suck it up or move elsewhere.
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.
Does that mean initializing the mutex before main?
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.ht...) which doesn't require a OnceCell/Lazy/lazy_static around it.
> They don’t want the mutex to contain data, just a lock.
> They don’t want to have to manage a “guard” value that unlocks the mutex on drop [...]
Really? Who think that? Comming from C++ myself, when learning Rust, I immediately liked the Mutex API for these reasons.