Replacement for std::sync::Semaphore since it is deprecated?
Sophia Terry
The documentation says it is deprecated. What's the system semaphore? And what's the best replacement for this struct now?
0Deprecated since 1.7.0: easily confused with system semaphore and not used enough to pull its weight
1 Answer
System semaphore refers to whatever semaphore the operating system provides. On POSIX (Linux, MacOS) these are the methods you get from #include <semaphore.h> (man page). std::sync::Semaphore was implemented in rust and was separate from the OS's semaphore, although it did use some OS level synchronization primitives (std::sync::Condvar which is based on pthread_cond_t on linux).std::sync::Semaphore was never stabilized. The source code for Semaphore contains an unstable attribute
#![unstable(feature = "semaphore", reason = "the interaction between semaphores and the acquisition/release \ of resources is currently unclear", issue = "27798")]The issue number in the header specifies the discussion about this feature.
The best replacement within std is either a std::sync::CondVar or a busy loop paired with a std::sync::Mutex. Pick a CondVar over a busy loop if you think you might be waiting more than a few thousand clock cycles.
The documentation for Condvar has a good example of how to use it as a (binary) semaphore
use std::sync::{Arc, Mutex, Condvar};
use std::thread;
let pair = Arc::new((Mutex::new(false), Condvar::new()));
let pair2 = Arc::clone(&pair);
// Inside of our lock, spawn a new thread, and then wait for it to start.
thread::spawn(move|| { let (lock, cvar) = &*pair2; let mut started = lock.lock().unwrap(); *started = true; // We notify the condvar that the value has changed. cvar.notify_one();
});
// Wait for the thread to start up.
let (lock, cvar) = &*pair;
let mut started = lock.lock().unwrap();
while !*started { started = cvar.wait(started).unwrap();
}This example could be adapted to work as a counting semaphore by changing Mutex::new(false) to Mutex::new(0) and a few corresponding changes.