From e394ebda37bf6bbe4c516e2b9381aac8bd964dcc Mon Sep 17 00:00:00 2001 From: Eric Holk Date: Wed, 6 Jun 2012 15:06:24 -0700 Subject: Adding a lock/condition variable to libcore. --- src/libcore/sys.rs | 72 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) (limited to 'src/libcore') diff --git a/src/libcore/sys.rs b/src/libcore/sys.rs index e0fd21f6c4a..90ea10601ae 100644 --- a/src/libcore/sys.rs +++ b/src/libcore/sys.rs @@ -7,6 +7,7 @@ export min_align_of; export pref_align_of; export refcount; export log_str; +export lock_and_signal, condition, methods; enum type_desc = { first_param: **libc::c_int, @@ -15,11 +16,20 @@ enum type_desc = { // Remaining fields not listed }; +type rust_cond_lock = *libc::c_void; + #[abi = "cdecl"] native mod rustrt { pure fn refcount(t: *()) -> libc::intptr_t; fn unsupervise(); pure fn shape_log_str(t: *sys::type_desc, data: *()) -> str; + + fn rust_create_cond_lock() -> rust_cond_lock; + fn rust_destroy_cond_lock(lock: rust_cond_lock); + fn rust_lock_cond_lock(lock: rust_cond_lock); + fn rust_unlock_cond_lock(lock: rust_cond_lock); + fn rust_wait_cond_lock(lock: rust_cond_lock); + fn rust_signal_cond_lock(lock: rust_cond_lock) -> bool; } #[abi = "rust-intrinsic"] @@ -74,8 +84,50 @@ pure fn log_str(t: T) -> str { } } +resource lock_and_signal(lock: rust_cond_lock) { + rustrt::rust_destroy_cond_lock(lock); +} + +enum condition { + condition_(rust_cond_lock) +} + +resource unlock(lock: rust_cond_lock) { + rustrt::rust_unlock_cond_lock(lock); +} + +fn create_lock() -> lock_and_signal { + lock_and_signal(rustrt::rust_create_cond_lock()) +} + +impl methods for lock_and_signal { + fn lock(f: fn() -> T) -> T { + rustrt::rust_lock_cond_lock(*self); + let _r = unlock(*self); + f() + } + + fn lock_cond(f: fn(condition) -> T) -> T { + rustrt::rust_lock_cond_lock(*self); + let _r = unlock(*self); + f(condition_(*self)) + } +} + +impl methods for condition { + fn wait() { + rustrt::rust_wait_cond_lock(*self); + } + + fn signal() -> bool { + rustrt::rust_signal_cond_lock(*self) + } +} + #[cfg(test)] mod tests { + use std; + import std::arc; #[test] fn size_of_basic() { @@ -121,6 +173,26 @@ mod tests { assert pref_align_of::() == 8u; assert pref_align_of::<*uint>() == 8u; } + + #[test] + fn condition_variable() { + let lock = arc::arc(create_lock()); + let lock2 = arc::clone(&lock); + + task::spawn {|move lock2| + let lock = arc::get(&lock2); + (*lock).lock_cond {|c| + c.wait(); + } + } + + let mut signaled = false; + while !signaled { + (*arc::get(&lock)).lock_cond {|c| + signaled = c.signal() + } + } + } } // Local Variables: -- cgit 1.4.1-3-g733a5