Skip to content

Commit 91de538

Browse files
committed
add rust_trylock_little_lock
Try to acquire lock and succeed only if lock is not already held. Uses TryEnterCriticalSection or pthread_mutex_trylock.
1 parent 2b2a89d commit 91de538

File tree

5 files changed

+49
-1
lines changed

5 files changed

+49
-1
lines changed

src/libstd/unstable/sync.rs

+16-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ use cell::Cell;
1313
use comm;
1414
use libc;
1515
use ptr;
16-
use option::*;
16+
use option::{Option,Some,None};
1717
use task;
1818
use unstable::atomics::{AtomicOption,AtomicUint,Acquire,Release,Relaxed,SeqCst};
1919
use unstable::finally::Finally;
@@ -354,6 +354,20 @@ impl LittleLock {
354354
}
355355
}
356356

357+
pub unsafe fn try_lock<T>(&self, f: &fn() -> T) -> Option<T> {
358+
do atomically {
359+
if rust_trylock_little_lock(self.l) {
360+
Some(do (|| {
361+
f()
362+
}).finally {
363+
rust_unlock_little_lock(self.l);
364+
})
365+
} else {
366+
None
367+
}
368+
}
369+
}
370+
357371
pub unsafe fn signal(&self) {
358372
rust_signal_little_lock(self.l);
359373
}
@@ -478,6 +492,7 @@ impl<T:Send> Exclusive<T> {
478492
extern {
479493
fn rust_create_little_lock() -> rust_little_lock;
480494
fn rust_destroy_little_lock(lock: rust_little_lock);
495+
fn rust_trylock_little_lock(lock: rust_little_lock) -> bool;
481496
fn rust_lock_little_lock(lock: rust_little_lock);
482497
fn rust_unlock_little_lock(lock: rust_little_lock);
483498
fn rust_signal_little_lock(lock: rust_little_lock);

src/rt/rust_builtin.cpp

+5
Original file line numberDiff line numberDiff line change
@@ -394,6 +394,11 @@ rust_lock_little_lock(lock_and_signal *lock) {
394394
lock->lock();
395395
}
396396

397+
extern "C" bool
398+
rust_trylock_little_lock(lock_and_signal *lock) {
399+
return lock->try_lock();
400+
}
401+
397402
extern "C" void
398403
rust_unlock_little_lock(lock_and_signal *lock) {
399404
lock->unlock();

src/rt/rustrt.def.in

+1
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ rust_dbg_do_nothing
3737
rust_create_little_lock
3838
rust_destroy_little_lock
3939
rust_lock_little_lock
40+
rust_trylock_little_lock
4041
rust_unlock_little_lock
4142
rust_signal_little_lock
4243
rust_wait_little_lock

src/rt/sync/lock_and_signal.cpp

+26
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,32 @@ void lock_and_signal::lock() {
8383
#endif
8484
}
8585

86+
bool lock_and_signal::try_lock() {
87+
must_not_have_lock();
88+
#if defined(__WIN32__)
89+
if (TryEnterCriticalSection(&_cs)) {
90+
#if defined(DEBUG_LOCKS)
91+
_holding_thread = GetCurrentThreadId();
92+
#endif
93+
return true;
94+
}
95+
#else // non-windows
96+
int trylock = pthread_mutex_trylock(&_mutex);
97+
if (trylock == 0) {
98+
#if defined(DEBUG_LOCKS)
99+
_holding_thread = pthread_self();
100+
#endif
101+
return true;
102+
} else if (trylock == EBUSY) {
103+
// EBUSY means lock was already held by someone else
104+
return false;
105+
}
106+
// abort on all other errors
107+
CHECKED(trylock);
108+
#endif
109+
return false;
110+
}
111+
86112
void lock_and_signal::unlock() {
87113
must_have_lock();
88114
#if defined(DEBUG_LOCKS)

src/rt/sync/lock_and_signal.h

+1
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ class lock_and_signal {
4343
virtual ~lock_and_signal();
4444

4545
void lock();
46+
bool try_lock();
4647
void unlock();
4748
void wait();
4849
void signal();

0 commit comments

Comments
 (0)