semaphore 0.4.0

Atomic/lock-free counting semaphore
Documentation
use std::sync::atomic::{AtomicUsize, Ordering};

use parking_lot::{Condvar, Mutex};

pub struct RawSemaphore {
    active: AtomicUsize,
    capacity: usize,
    lock: Mutex<()>,
    cond: Condvar
}

impl RawSemaphore {
    pub fn new(capacity: usize) -> RawSemaphore {
        RawSemaphore {
            active: AtomicUsize::default(),
            capacity: capacity,
            lock: Mutex::new(()),
            cond: Condvar::new()
        }
    }

    #[inline]
    pub fn try_acquire(&self) -> bool {
        loop {
            let current_active = self.active.load(Ordering::SeqCst);
            assert!(current_active <= self.capacity);
            if current_active == self.capacity {
                return false;
            }
            let previous_active = self.active.compare_and_swap(
                current_active,
                current_active + 1,
                Ordering::SeqCst
            );
            if previous_active == current_active {
                return true;
            }
        }
    }

    #[inline]
    pub fn release(&self) {
        let previous_active = self.active.fetch_sub(1, Ordering::SeqCst);
        if previous_active == 1 {
            let guard = self.lock.lock();
            self.cond.notify_all();
            drop(guard)
        }
    }

    #[inline]
    pub fn is_active(&self) -> bool {
        self.active.load(Ordering::SeqCst) > 0
    }

    #[inline]
    pub fn wait_until_inactive(&self) {
        let mut lock = self.lock.lock();

        while self.is_active() {
            self.cond.wait(&mut lock);
        }
    }
}