diff --git a/src/libstd/unstable/sync.rs b/src/libstd/unstable/sync.rs index a08b914ca31..0e1f5fc1bdc 100644 --- a/src/libstd/unstable/sync.rs +++ b/src/libstd/unstable/sync.rs @@ -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(&self, f: &fn() -> T) -> Option { + 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 Exclusive { 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); diff --git a/src/rt/rust_builtin.cpp b/src/rt/rust_builtin.cpp index 90042491d1d..4c1c6a7202a 100644 --- a/src/rt/rust_builtin.cpp +++ b/src/rt/rust_builtin.cpp @@ -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(); diff --git a/src/rt/rustrt.def.in b/src/rt/rustrt.def.in index 3b581e94be7..1f440047d4e 100644 --- a/src/rt/rustrt.def.in +++ b/src/rt/rustrt.def.in @@ -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 diff --git a/src/rt/sync/lock_and_signal.cpp b/src/rt/sync/lock_and_signal.cpp index 3d7ad02c438..fcf8ab5d88b 100644 --- a/src/rt/sync/lock_and_signal.cpp +++ b/src/rt/sync/lock_and_signal.cpp @@ -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) diff --git a/src/rt/sync/lock_and_signal.h b/src/rt/sync/lock_and_signal.h index 5a0eb83a394..45e1f719851 100644 --- a/src/rt/sync/lock_and_signal.h +++ b/src/rt/sync/lock_and_signal.h @@ -43,6 +43,7 @@ public: virtual ~lock_and_signal(); void lock(); + bool try_lock(); void unlock(); void wait(); void signal();