use {atomic};
use core::{mem};
use core::ops::{Eq};
use cell::{Cell};
pub struct SingleThreadLock {
down_lock: Cell<bool>,
up_lock: Cell<bool>,
}
impl Eq for SingleThreadLock {
fn eq(&self, other: &SingleThreadLock) -> bool {
mem::addr(self) == mem::addr(other)
}
}
impl !Sync for SingleThreadLock { }
unsafe impl Interrupt for SingleThreadLock { }
unsafe impl Send for SingleThreadLock { }
impl SingleThreadLock {
pub const fn new() -> SingleThreadLock {
SingleThreadLock {
down_lock: Cell::new(false),
up_lock: Cell::new(false),
}
}
pub fn locked(&self) -> bool {
self.down_lock.get()
}
pub fn lock<'a>(&'a self) -> SingleThreadLockGuard<'a> {
self.try_lock().unwrap()
}
pub fn try_lock<'a>(&'a self) -> Option<SingleThreadLockGuard<'a>> {
let locked = self.down_lock.get();
self.down_lock.set(true);
atomic::single_thread_fence_acquire_release();
if locked | self.up_lock.get() {
None
} else {
self.up_lock.set(true);
Some(SingleThreadLockGuard {
lock: &self
})
}
}
}
pub struct SingleThreadLockGuard<'a> {
lock: &'a SingleThreadLock,
}
impl<'a> SingleThreadLockGuard<'a> {
pub fn as_lock(&self) -> &'a SingleThreadLock {
self.lock
}
pub fn unlock(self) -> &'a SingleThreadLock {
self.lock
}
}
impl<'a> Drop for SingleThreadLockGuard<'a> {
fn drop(&mut self) {
self.lock.up_lock.set(false);
atomic::single_thread_fence_release();
self.lock.down_lock.set(false);
}
}