Earlier quoted context omitted.
That’s not surprising to me, but it’s not much of an argument for changing the default to be less safe. Most people want poisoning to propagate fatal errors and avoid reading corrupted data, not to recover from panics. Edit: isn’t that an argument not to change the default? If people were recovering from poison a lot and that was painful, that’s one thing. But if people aren’t doing that, why is this a problem?
Because right now everyone writes `.lock().unwrap()` everywhere without really thinking about it, and it just makes Mutex more painful to work with.
Inside Rust's std and parking_lot mutexes – who wins?
111–120 of 134 posts
Re: Inside Rust's std and parking_lot mutexes – who wins?
#112Earlier quoted context omitted.
A panic in single-threaded, non-parallel code will either terminate the program or be recovered cleanly, so the potential for side effects to be silently observed in a way that breaks invariants is unique to Mutex . This is the reason for mutex poisoning,
I fail to see that there is any material difference. Whether you catch-unwind within a single thread or in a separate thread such that the panic can be resumed on join makes zero difference. Heck, you can have Drop impls observing the state while unwinding . A true panic-safe data structure requires serious thought, and mutex poisoning does nothing here - it is neither necessary nor sufficient.
This seems analogous to arguing that because seat belts don't save the lives of all people involved in car crashes, and they're kind of annoying, then they shouldn't be factory-standard.
Re: Inside Rust's std and parking_lot mutexes – who wins?
#113Earlier quoted context omitted.
> and neither do the webkit.org articles that describe the parking lot concept but not this Rust implementation The WebKit post explicitly talks about how you just need two bits to describe the lock state. > The correct answer appears to be that it's impossible: `parking_lot::RawMutex` has private storage that owns the entire byte and does not provide any accessor for the unused six bits. Not impossible. One way to d…
> The WebKit post explicitly talks about how you just need two bits to describe the lock state. It describes the algorithm but not how a caller of the Rust `parking_lot` crate could take advantage of this. > Not impossible. One way to do this is to just use parking_lot directly. By "just use parking_lot directly", I think you're talking about reimplementing the parking lot algorithm or using the C++ `WTF::ParkingLot`…
Read the WebKit post.
> By "just use parking_lot directly", I think you're talking about reimplementing the parking lot algorithm or using the C++ `WTF::ParkingLot` implementation? But not actually using the existing Rust crate called `parking_lot` described in the cuongle.dev article?
See https://docs.rs/parking_lot_core/latest/parking_lot_core/
That's my ParkingLot API. You can use it to implement many kinds of locks, including:
- Efficient ones that use a tristate, like the glibc lowlevellock, or what I call the Cascade lock. So, this doesn't even need two bits.
- The lock algorithm I prefer, which uses two bits.
- Lots of other algorithms. You can do very efficient condition variables, rwlocks, counting locks, etc.
You can do a lot of useful algorithms with fewer than 8 bits. You don't have to use the C++ ParkingLot. You don't have to implement parking_lot.
What you do have to do is RTFM
Re: Inside Rust's std and parking_lot mutexes – who wins?
#114Earlier quoted context omitted.
Because right now everyone writes `.lock().unwrap()` everywhere without really thinking about it, and it just makes Mutex more painful to work with.
You seem to keep making the implicit assumption that because people are using `unwrap()`, they must not care about the poisoning behavior. I really don't understand where this assumption is coming from. I explicitly want to propagate panics from contexts that hold locks to contexts that take locks. The way to write that is `lock().unwrap()`. I get that some people might write `lock().unwrap()` not because they care a…
I'm suggesting that the balance of pain to benefit is not working out enough to inflict it on everyone by default. I'm not suggesting it has no value, just not enough to be worth it.
Re: Inside Rust's std and parking_lot mutexes – who wins?
#115Earlier quoted context omitted.
I fail to see that there is any material difference. Whether you catch-unwind within a single thread or in a separate thread such that the panic can be resumed on join makes zero difference. Heck, you can have Drop impls observing the state while unwinding . A true panic-safe data structure requires serious thought, and mutex poisoning does nothing here - it is neither necessary nor sufficient.
This is a false dichotomy. Not every technique needs to work in all cases in order to be useful. This seems analogous to arguing that because seat belts don't save the lives of all people involved in car crashes, and they're kind of annoying, then they shouldn't be factory-standard.
Re: Inside Rust's std and parking_lot mutexes – who wins?
#116Earlier quoted context omitted.
I've used recovering from poisoned state in impl Drop in quite a few places. In my case it's usually waiting for the GPU to finish some asynchronous work that's been spun up by CPU threads that may have panicked while holding the lock. This is necessary to avoid freeing resources that the GPU may still be using. I usually prefix this with `if !std::thread::panicking() {}`, so I don't end up waiting (possibly forever)…
Thank you for mentioning this; I'd be really interested in hearing more about this, and seeing some examples.
I have a container of resources, e.g. textures. When the GPU wants to use them, CPU will lease them until a point of time in the future denoted by a value (u64) of a GPU timeline semaphore. The handle and value of the semaphore is added to a list guarded by a mutex. Then GPU work is kicked off and the GPU will increment semaphore to that value when done.
In the Drop implementation of the container, we need to wait until all semaphores reach their respective value before freeing resources, and do so even if some thread panicked while holding the lock guarding the list. This is where I use .unwrap_or_else to get the list from the poison value.
It's not infeasible to try to catch any errors and propagate them when the lock is grabbed. But this is mostly for OOM and asserts that are not expected to fire. The ergonomics would be worse if the "lease" function would be fallible.
This said, I would not object to poisoning being made optional.
Re: Inside Rust's std and parking_lot mutexes – who wins?
#117Earlier quoted context omitted.
When comparing languages, posting unidiomatic code, and then making claims based on that unidiomatic code, is generally not fair nor correct.
That's true if the claims hinge on said unidiomatic code. As I said, it's not clear to me that that is the case here.
Re: Inside Rust's std and parking_lot mutexes – who wins?
#118Earlier quoted context omitted.
That's true if the claims hinge on said unidiomatic code. As I said, it's not clear to me that that is the case here.
It seems completely clear. He first gives unidiomatic C++ code, then next gives idiomatic Rust code, and differentiates the two based on the code snippets. It is a mistake on his part, and I do not see how it could reasonably be viewed otherwise. It is not a huge mistake, but it is still a clear mistake.
From my reading, the section (and the article in general, really) is specifically focusing on mutexes, so the observations the article makes are indeed accurate in that respect (i.e., C++'s std::mutex indeed does not have automatic unlocking; you need to use an external construct for that functionality). Now, if the article were talking about locking patterns more generally, I think your criticism would hold more weight, but I think the article is more narrowly focused than that.
For a bit of a more speculative read, I think it's not unreasonable to take the C++ code as a general demonstration of the mutex API "languages other than Rust" use rather than trying to be a more specific comparison of locking patterns in Rust and C++. Consider the preceding paragraph:
> In languages other than Rust, you typically declare a mutex separately from your data, then manually lock it before entering the critical section and unlock it afterward. Here’s how it looks in C++:
I don't think it's unreasonable to read the "it" in the final sentence as "that pattern"; i.e., "Here's what that pattern looks like when written in C++". The example code would be perfectly correct in that case - it shows a mutex declared separately from the data, and it shows that mutex being manually locked before entering the critical section and unlocked after.
Re: Inside Rust's std and parking_lot mutexes – who wins?
#119Earlier quoted context omitted.
It seems completely clear. He first gives unidiomatic C++ code, then next gives idiomatic Rust code, and differentiates the two based on the code snippets. It is a mistake on his part, and I do not see how it could reasonably be viewed otherwise. It is not a huge mistake, but it is still a clear mistake.
Perhaps it might help to clarify precisely what claim(s) you think are being made? From my reading, the section (and the article in general, really) is specifically focusing on mutexes, so the observations the article makes are indeed accurate in that respect (i.e., C++'s std::mutex indeed does not have automatic unlocking; you need to use an external construct for that functionality). Now, if the article were talkin…
Re: Inside Rust's std and parking_lot mutexes – who wins?
#120Earlier quoted context omitted.
For the simple case, suppose that you're writing a TUI application that takes over the terminal. When it exits, even by panic, you want to clean up the terminal state so the user doesn't have to blindly type "reset". Today, people sometimes do that by using `panic = "unwind"`, and writing a `catch_unwind` around their program, and using that to essentially implement a "finally" block. Or, they do it by having an RAII…
I have not given it much thought, but it would primarily be for the subset of Rust programs that do not need zero-cost abstractions as much, right? Since, even in the case of no panics, one would be paying at runtime for registering panic hooks, if I understand correctly.