mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 23:04:33 +00:00
Adding a lock/condition variable to libcore.
This commit is contained in:
parent
5c9f414a85
commit
e394ebda37
1
mk/rt.mk
1
mk/rt.mk
@ -70,6 +70,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 \
|
||||
|
@ -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:
|
||||
|
@ -7,6 +7,7 @@
|
||||
#include "sync/timer.h"
|
||||
#include "rust_abi.h"
|
||||
#include "rust_port.h"
|
||||
#include "rust_cond_lock.h"
|
||||
|
||||
#include <time.h>
|
||||
|
||||
@ -862,6 +863,60 @@ 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;
|
||||
lock->lock.unlock();
|
||||
task->block(lock, "waiting for signal");
|
||||
lock->lock.lock();
|
||||
lock->waiting = NULL;
|
||||
}
|
||||
|
||||
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);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//
|
||||
// Local Variables:
|
||||
// mode: C++
|
||||
|
6
src/rt/rust_cond_lock.cpp
Normal file
6
src/rt/rust_cond_lock.cpp
Normal 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
15
src/rt/rust_cond_lock.h
Normal 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;
|
||||
};
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user