You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
70 lines
2.1 KiB
70 lines
2.1 KiB
//! A counting, blocking, semaphore.
|
|
//!
|
|
//! Same as [std::sync::Semaphore at rust 1.7.0](https://docs.rs/std-semaphore/0.1.0/std_semaphore/)
|
|
|
|
use super::Condvar;
|
|
use super::SpinNoIrqLock as Mutex;
|
|
|
|
/// A counting, blocking, semaphore.
|
|
pub struct Semaphore {
|
|
lock: Mutex<isize>,
|
|
cvar: Condvar,
|
|
}
|
|
|
|
/// An RAII guard which will release a resource acquired from a semaphore when
|
|
/// dropped.
|
|
pub struct SemaphoreGuard<'a> {
|
|
sem: &'a Semaphore,
|
|
}
|
|
|
|
impl Semaphore {
|
|
/// Creates a new semaphore with the initial count specified.
|
|
///
|
|
/// The count specified can be thought of as a number of resources, and a
|
|
/// call to `acquire` or `access` will block until at least one resource is
|
|
/// available. It is valid to initialize a semaphore with a negative count.
|
|
pub fn new(count: isize) -> Semaphore {
|
|
Semaphore {
|
|
lock: Mutex::new(count),
|
|
cvar: Condvar::new(),
|
|
}
|
|
}
|
|
|
|
/// Acquires a resource of this semaphore, blocking the current thread until
|
|
/// it can do so.
|
|
///
|
|
/// This method will block until the internal count of the semaphore is at
|
|
/// least 1.
|
|
pub fn acquire(&self) {
|
|
let mut count = self.lock.lock();
|
|
while *count <= 0 {
|
|
count = self.cvar.wait(count);
|
|
}
|
|
*count -= 1;
|
|
}
|
|
|
|
/// Release a resource from this semaphore.
|
|
///
|
|
/// This will increment the number of resources in this semaphore by 1 and
|
|
/// will notify any pending waiters in `acquire` or `access` if necessary.
|
|
pub fn release(&self) {
|
|
*self.lock.lock() += 1;
|
|
self.cvar.notify_one();
|
|
}
|
|
|
|
/// Acquires a resource of this semaphore, returning an RAII guard to
|
|
/// release the semaphore when dropped.
|
|
///
|
|
/// This function is semantically equivalent to an `acquire` followed by a
|
|
/// `release` when the guard returned is dropped.
|
|
pub fn access(&self) -> SemaphoreGuard {
|
|
self.acquire();
|
|
SemaphoreGuard { sem: self }
|
|
}
|
|
}
|
|
|
|
impl<'a> Drop for SemaphoreGuard<'a> {
|
|
fn drop(&mut self) {
|
|
self.sem.release();
|
|
}
|
|
} |