Semaphore (not tested)

master
WangRunji 7 years ago
parent cb4f82b2a9
commit 37d2497de3

@ -1,6 +1,6 @@
mod mutex;
mod condvar;
//mod semaphore;
mod semaphore;
pub mod test;
pub use self::mutex::*;

@ -1,2 +1,73 @@
use super::mutex;
//! A counting, blocking, semaphore.
//!
//! Borrowed from std at rust 1.7.0
use super::SpinNoIrqLock as Mutex;
use super::Condvar;
/// 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 {
// TODO: -> cvar.wait(count)
drop(count);
self.cvar.wait();
count = self.lock.lock();
}
*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();
}
}
Loading…
Cancel
Save