Browse Source

Initial rwlock impl

pull/10/head
Fenrir 7 years ago committed by FenrirWolf
parent
commit
4977dcb167
  1. 58
      ctr-std/src/sys/unix/rwlock.rs

58
ctr-std/src/sys/unix/rwlock.rs

@ -8,10 +8,16 @@
// option. This file may not be copied, modified, or distributed // option. This file may not be copied, modified, or distributed
// except according to those terms. // except according to those terms.
use cell::UnsafeCell;
use super::mutex::Mutex; use super::mutex::Mutex;
use super::condvar::Condvar;
// A simple read-preferring RWLock implementation that I found on wikipedia <.<
pub struct RWLock { pub struct RWLock {
mutex: Mutex mutex: Mutex,
cvar: Condvar,
reader_count: UnsafeCell<u8>, // Is 255 potential readers enough? I would hope so, but idk
writer_active: UnsafeCell<bool>,
} }
unsafe impl Send for RWLock {} unsafe impl Send for RWLock {}
@ -20,42 +26,86 @@ unsafe impl Sync for RWLock {}
impl RWLock { impl RWLock {
pub const fn new() -> RWLock { pub const fn new() -> RWLock {
RWLock { RWLock {
mutex: Mutex::new() mutex: Mutex::new(),
cvar: Condvar::new(),
reader_count: UnsafeCell::new(0),
writer_active: UnsafeCell::new(false),
} }
} }
#[inline] #[inline]
pub unsafe fn read(&self) { pub unsafe fn read(&self) {
self.mutex.lock(); self.mutex.lock();
while *self.writer_active.get() {
self.cvar.wait(&self.mutex);
}
*self.reader_count.get() += 1;
self.mutex.unlock();
} }
#[inline] #[inline]
pub unsafe fn try_read(&self) -> bool { pub unsafe fn try_read(&self) -> bool {
self.mutex.try_lock() if !self.mutex.try_lock() {
return false
}
while *self.writer_active.get() {
self.cvar.wait(&self.mutex);
}
*self.reader_count.get() += 1;
self.mutex.unlock();
true
} }
#[inline] #[inline]
pub unsafe fn write(&self) { pub unsafe fn write(&self) {
self.mutex.lock(); self.mutex.lock();
while *self.writer_active.get() || *self.reader_count.get() > 0 {
self.cvar.wait(&self.mutex);
}
*self.writer_active.get() = true;
self.mutex.unlock();
} }
#[inline] #[inline]
pub unsafe fn try_write(&self) -> bool { pub unsafe fn try_write(&self) -> bool {
self.mutex.try_lock() if !self.mutex.try_lock() {
return false;
}
while *self.writer_active.get() || *self.reader_count.get() > 0 {
self.cvar.wait(&self.mutex);
}
*self.writer_active.get() = true;
self.mutex.unlock();
true
} }
#[inline] #[inline]
pub unsafe fn read_unlock(&self) { pub unsafe fn read_unlock(&self) {
self.mutex.lock();
*self.reader_count.get() -= 1;
if *self.reader_count.get() == 0 {
self.cvar.notify_one()
}
self.mutex.unlock(); self.mutex.unlock();
} }
#[inline] #[inline]
pub unsafe fn write_unlock(&self) { pub unsafe fn write_unlock(&self) {
self.mutex.lock();
*self.writer_active.get() = false;
self.cvar.notify_one();
self.mutex.unlock(); self.mutex.unlock();
} }
#[inline] #[inline]
pub unsafe fn destroy(&self) { pub unsafe fn destroy(&self) {
self.mutex.destroy(); self.mutex.destroy();
self.cvar.destroy();
*self.reader_count.get() = 0;
*self.writer_active.get() = false;
} }
} }

Loading…
Cancel
Save