Adding a lock/condition variable to libcore.

This commit is contained in:
Eric Holk 2012-06-06 15:06:24 -07:00
parent 9ee1480fd1
commit dc718d97a6
6 changed files with 156 additions and 0 deletions

View File

@ -71,6 +71,7 @@ RUNTIME_CS_$(1) := \
rt/rust_cc.cpp \
rt/rust_debug.cpp \
rt/rust_box_annihilator.cpp \
rt/rust_cond_lock.cpp \
rt/memory_region.cpp \
rt/boxed_region.cpp \
rt/arch/$$(HOST_$(1))/context.cpp \

View File

@ -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:

View File

@ -7,6 +7,7 @@
#include "sync/timer.h"
#include "rust_abi.h"
#include "rust_port.h"
#include "rust_cond_lock.h"
#include <time.h>
@ -861,6 +862,61 @@ rust_task_allow_kill() {
task->allow_kill();
}
extern "C" rust_cond_lock*
rust_create_cond_lock() {
return new rust_cond_lock();
}
extern "C" void
rust_destroy_cond_lock(rust_cond_lock *lock) {
delete lock;
}
extern "C" void
rust_lock_cond_lock(rust_cond_lock *lock) {
lock->lock.lock();
}
extern "C" void
rust_unlock_cond_lock(rust_cond_lock *lock) {
lock->lock.unlock();
}
// The next two functions do not use the built in condition variable features
// because the Rust schedule is not aware of them, and they can block the
// scheduler thread.
extern "C" void
rust_wait_cond_lock(rust_cond_lock *lock) {
rust_task *task = rust_get_current_task();
#ifdef DEBUG_LOCKS
assert(lock->lock.lock_held_by_current_thread());
#endif
assert(NULL == lock->waiting);
lock->waiting = task;
task->block(lock, "waiting for signal");
lock->lock.unlock();
task->yield(false);
lock->lock.lock();
}
extern "C" bool
rust_signal_cond_lock(rust_cond_lock *lock) {
#ifdef DEBUG_LOCKS
assert(lock->lock.lock_held_by_current_thread());
#endif
if(NULL == lock->waiting) {
return false;
}
else {
lock->waiting->wakeup(lock);
lock->waiting = NULL;
return true;
}
}
//
// Local Variables:
// mode: C++

View File

@ -0,0 +1,6 @@
#include "rust_cond_lock.h"
rust_cond_lock::rust_cond_lock()
: waiting(NULL)
{
}

15
src/rt/rust_cond_lock.h Normal file
View File

@ -0,0 +1,15 @@
// -*- c++ -*-
// A lock and condition variable pair that is useable from Rust.
#pragma once
#include "sync/lock_and_signal.h"
#include "rust_globals.h"
#include "rust_task.h"
struct rust_cond_lock : public rust_cond {
rust_cond_lock();
lock_and_signal lock;
rust_task *waiting;
};

View File

@ -163,3 +163,9 @@ rust_port_drop
rust_port_task
rust_task_inhibit_kill
rust_task_allow_kill
rust_create_cond_lock
rust_destroy_cond_lock
rust_lock_cond_lock
rust_unlock_cond_lock
rust_wait_cond_lock
rust_signal_cond_lock