Al-Qudsi: Implementing truly safe semaphores in rust
source link: https://lwn.net/Articles/910417/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
Al-Qudsi: Implementing truly safe semaphores in rust
The problem is that with n > 1, there’s no concept of a “privileged” owning thread and all threads that have “obtained” the semaphore do so equally. Therefore, a rust semaphore can only ever provide read-only (&T) access to an underlying resource, limiting the usefulness of such a semaphore almost to the point of having no utility. As such, the only safe “owning” semaphore with read-write access that can exist in the rust world would be Semaphore<()>, or one that actually owns no data and can only be used for its side effect of limiting concurrency while the semaphore is “owned,” so to speak.
(Log in to post comments)
Al-Qudsi: Implementing truly safe semaphores in rust
Posted Oct 5, 2022 17:37 UTC (Wed) by jezuch (subscriber, #52988) [Link]
Well ok then, what is it good for?
Al-Qudsi: Implementing truly safe semaphores in rust
Posted Oct 5, 2022 19:33 UTC (Wed) by excors (subscriber, #95769) [Link]
I suspect the article is wrong though. "&T" does not mean "read-only". It means the language won't let you assign to the object's fields directly (because it's not an exclusive reference, so the compiler can't be sure you won't assign in two threads concurrently and cause a data race), but the object may still support interior mutability - e.g. it can contain an AtomicU32 which has functions that can safely mutate it through a &T with no risk of data races.
More usefully it could contain a Mutex (which converts a shared reference "&Mutex<T>" to an exclusive reference "&mut T", but only for one thread at a time). You'd use the semaphore so that only N threads can perform some high-level operation concurrently (maybe you only want 4 HTTP requests at once), while the &T uses fine-grained mutexes around any shared mutable data as normal.
I haven't read the article very carefully but I'm not sure why they don't that. As far as I can see, their design has no explicit link between the semaphore and the thing protected by the semaphore (e.g. the object providing the HTTP request API), even though the thing protected by the semaphore must still be accessed by all the threads through some shared &T (which internally uses atomics/mutexes/etc) because that's the only way to share things between threads in Rust. You could (I think) store that &T inside the semaphore object and return it from the wait() function, and that would make it harder to accidentally write code that forgets to acquire the semaphore before using the associated &T. It wouldn't matter in terms of Rust's safety guarantees, but it seems like that'd be an easier-to-use API.
Al-Qudsi: Implementing truly safe semaphores in rust
Posted Oct 5, 2022 19:58 UTC (Wed) by Karellen (subscriber, #67644) [Link]
There may be cases where limiting a resource to having n concurrent readers (and zero writers) has some greater-than-zero utility, which the naive rust semaphore would support.
Al-Qudsi: Implementing truly safe semaphores in rust
Posted Oct 5, 2022 19:40 UTC (Wed) by riking (subscriber, #95706) [Link]
Al-Qudsi: Implementing truly safe semaphores in rust
Posted Oct 6, 2022 12:23 UTC (Thu) by willy (subscriber, #9762) [Link]
Al-Qudsi: Implementing truly safe semaphores in rust
Posted Oct 6, 2022 1:40 UTC (Thu) by nyanpasu64 (subscriber, #135579) [Link]
Binary semaphores aren't useful for purely locking data (wrapping and protecting state), but I still want them for coordinating between threads (transmitting state in of themselves). Unlike mutexes, they allow any thread to release a token, not just a thread (if any) that just acquired one, which is useful in situations where you'd otherwise use a condition variable. Condition variables are actually surprisingly tricky to use right, and using one to simulate a binary semaphore will lead to race conditions if you don't keep a separate condition boolean (alongside a mutex *and* condition variable) and only read it while holding the mutex (https://pvk.ca/Blog/2019/01/09/preemption-is-gc-for-memor...).
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK