summary refs log tree commit diff
path: root/src/libcore
diff options
context:
space:
mode:
authorEric Holk <eric.holk@gmail.com>2012-06-06 15:06:24 -0700
committerEric Holk <eric.holk@gmail.com>2012-06-15 22:00:24 -0400
commite394ebda37bf6bbe4c516e2b9381aac8bd964dcc (patch)
tree58128171af062efa394ee0d0697bcb52c29bb21e /src/libcore
parent5c9f414a85ae8f3448a27f56274afc861974cffe (diff)
downloadrust-e394ebda37bf6bbe4c516e2b9381aac8bd964dcc.tar.gz
rust-e394ebda37bf6bbe4c516e2b9381aac8bd964dcc.zip
Adding a lock/condition variable to libcore.
Diffstat (limited to 'src/libcore')
-rw-r--r--src/libcore/sys.rs72
1 files changed, 72 insertions, 0 deletions
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: 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<T>(f: fn() -> T) -> T {
+        rustrt::rust_lock_cond_lock(*self);
+        let _r = unlock(*self);
+        f()
+    }
+
+    fn lock_cond<T>(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::<uint>() == 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: