add rust_trylock_little_lock

Try to acquire lock and succeed only if lock is not already held.
Uses TryEnterCriticalSection or pthread_mutex_trylock.
This commit is contained in:
Jason Toffaletti 2013-11-11 13:33:43 -08:00
parent 2b2a89d97f
commit 91de538c98
5 changed files with 49 additions and 1 deletions

View File

@ -13,7 +13,7 @@ use cell::Cell;
use comm;
use libc;
use ptr;
use option::*;
use option::{Option,Some,None};
use task;
use unstable::atomics::{AtomicOption,AtomicUint,Acquire,Release,Relaxed,SeqCst};
use unstable::finally::Finally;
@ -354,6 +354,20 @@ impl LittleLock {
}
}
pub unsafe fn try_lock<T>(&self, f: &fn() -> T) -> Option<T> {
do atomically {
if rust_trylock_little_lock(self.l) {
Some(do (|| {
f()
}).finally {
rust_unlock_little_lock(self.l);
})
} else {
None
}
}
}
pub unsafe fn signal(&self) {
rust_signal_little_lock(self.l);
}
@ -478,6 +492,7 @@ impl<T:Send> Exclusive<T> {
extern {
fn rust_create_little_lock() -> rust_little_lock;
fn rust_destroy_little_lock(lock: rust_little_lock);
fn rust_trylock_little_lock(lock: rust_little_lock) -> bool;
fn rust_lock_little_lock(lock: rust_little_lock);
fn rust_unlock_little_lock(lock: rust_little_lock);
fn rust_signal_little_lock(lock: rust_little_lock);

View File

@ -394,6 +394,11 @@ rust_lock_little_lock(lock_and_signal *lock) {
lock->lock();
}
extern "C" bool
rust_trylock_little_lock(lock_and_signal *lock) {
return lock->try_lock();
}
extern "C" void
rust_unlock_little_lock(lock_and_signal *lock) {
lock->unlock();

View File

@ -37,6 +37,7 @@ rust_dbg_do_nothing
rust_create_little_lock
rust_destroy_little_lock
rust_lock_little_lock
rust_trylock_little_lock
rust_unlock_little_lock
rust_signal_little_lock
rust_wait_little_lock

View File

@ -83,6 +83,32 @@ void lock_and_signal::lock() {
#endif
}
bool lock_and_signal::try_lock() {
must_not_have_lock();
#if defined(__WIN32__)
if (TryEnterCriticalSection(&_cs)) {
#if defined(DEBUG_LOCKS)
_holding_thread = GetCurrentThreadId();
#endif
return true;
}
#else // non-windows
int trylock = pthread_mutex_trylock(&_mutex);
if (trylock == 0) {
#if defined(DEBUG_LOCKS)
_holding_thread = pthread_self();
#endif
return true;
} else if (trylock == EBUSY) {
// EBUSY means lock was already held by someone else
return false;
}
// abort on all other errors
CHECKED(trylock);
#endif
return false;
}
void lock_and_signal::unlock() {
must_have_lock();
#if defined(DEBUG_LOCKS)

View File

@ -43,6 +43,7 @@ public:
virtual ~lock_and_signal();
void lock();
bool try_lock();
void unlock();
void wait();
void signal();