parent
cb4f82b2a9
commit
37d2497de3
@ -1,6 +1,6 @@
|
|||||||
mod mutex;
|
mod mutex;
|
||||||
mod condvar;
|
mod condvar;
|
||||||
//mod semaphore;
|
mod semaphore;
|
||||||
pub mod test;
|
pub mod test;
|
||||||
|
|
||||||
pub use self::mutex::*;
|
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…
Reference in new issue