convert std::sync types to camelcase
This commit is contained in:
@@ -10,7 +10,8 @@ import unsafe::{SharedMutableState, shared_mutable_state,
|
|||||||
clone_shared_mutable_state, unwrap_shared_mutable_state,
|
clone_shared_mutable_state, unwrap_shared_mutable_state,
|
||||||
get_shared_mutable_state, get_shared_immutable_state};
|
get_shared_mutable_state, get_shared_immutable_state};
|
||||||
import sync;
|
import sync;
|
||||||
import sync::{mutex, mutex_with_condvars, rwlock, rwlock_with_condvars};
|
import sync::{Mutex, mutex, mutex_with_condvars,
|
||||||
|
RWlock, rwlock, rwlock_with_condvars};
|
||||||
|
|
||||||
export arc, clone, get;
|
export arc, clone, get;
|
||||||
export condvar, mutex_arc, mutex_arc_with_condvars, unwrap_mutex_arc;
|
export condvar, mutex_arc, mutex_arc_with_condvars, unwrap_mutex_arc;
|
||||||
@@ -18,7 +19,7 @@ export rw_arc, rw_arc_with_condvars, rw_write_mode, rw_read_mode;
|
|||||||
export unwrap_rw_arc;
|
export unwrap_rw_arc;
|
||||||
|
|
||||||
/// As sync::condvar, a mechanism for unlock-and-descheduling and signalling.
|
/// As sync::condvar, a mechanism for unlock-and-descheduling and signalling.
|
||||||
struct condvar { is_mutex: bool; failed: &mut bool; cond: &sync::condvar; }
|
struct condvar { is_mutex: bool; failed: &mut bool; cond: &sync::Condvar; }
|
||||||
|
|
||||||
impl &condvar {
|
impl &condvar {
|
||||||
/// Atomically exit the associated ARC and block until a signal is sent.
|
/// Atomically exit the associated ARC and block until a signal is sent.
|
||||||
@@ -113,7 +114,7 @@ fn unwrap<T: const send>(+rc: arc<T>) -> T {
|
|||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
struct mutex_arc_inner<T: send> { lock: mutex; failed: bool; data: T; }
|
struct mutex_arc_inner<T: send> { lock: Mutex; failed: bool; data: T; }
|
||||||
/// An ARC with mutable data protected by a blocking mutex.
|
/// An ARC with mutable data protected by a blocking mutex.
|
||||||
struct mutex_arc<T: send> { x: SharedMutableState<mutex_arc_inner<T>>; }
|
struct mutex_arc<T: send> { x: SharedMutableState<mutex_arc_inner<T>>; }
|
||||||
|
|
||||||
@@ -234,7 +235,7 @@ struct poison_on_fail {
|
|||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
struct rw_arc_inner<T: const send> { lock: rwlock; failed: bool; data: T; }
|
struct rw_arc_inner<T: const send> { lock: RWlock; failed: bool; data: T; }
|
||||||
/**
|
/**
|
||||||
* A dual-mode ARC protected by a reader-writer lock. The data can be accessed
|
* A dual-mode ARC protected by a reader-writer lock. The data can be accessed
|
||||||
* mutably or immutably, and immutably-accessing tasks may run concurrently.
|
* mutably or immutably, and immutably-accessing tasks may run concurrently.
|
||||||
@@ -383,7 +384,7 @@ fn unwrap_rw_arc<T: const send>(+arc: rw_arc<T>) -> T {
|
|||||||
// lock it. This wraps the unsafety, with the justification that the 'lock'
|
// lock it. This wraps the unsafety, with the justification that the 'lock'
|
||||||
// field is never overwritten; only 'failed' and 'data'.
|
// field is never overwritten; only 'failed' and 'data'.
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
fn borrow_rwlock<T: const send>(state: &r/mut rw_arc_inner<T>) -> &r/rwlock {
|
fn borrow_rwlock<T: const send>(state: &r/mut rw_arc_inner<T>) -> &r/RWlock {
|
||||||
unsafe { unsafe::transmute_immut(&mut state.lock) }
|
unsafe { unsafe::transmute_immut(&mut state.lock) }
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -391,9 +392,9 @@ fn borrow_rwlock<T: const send>(state: &r/mut rw_arc_inner<T>) -> &r/rwlock {
|
|||||||
|
|
||||||
/// The "write permission" token used for rw_arc.write_downgrade().
|
/// The "write permission" token used for rw_arc.write_downgrade().
|
||||||
enum rw_write_mode<T: const send> =
|
enum rw_write_mode<T: const send> =
|
||||||
(&mut T, sync::rwlock_write_mode, poison_on_fail);
|
(&mut T, sync::RWlockWriteMode, poison_on_fail);
|
||||||
/// The "read permission" token used for rw_arc.write_downgrade().
|
/// The "read permission" token used for rw_arc.write_downgrade().
|
||||||
enum rw_read_mode<T:const send> = (&T, sync::rwlock_read_mode);
|
enum rw_read_mode<T:const send> = (&T, sync::RWlockReadMode);
|
||||||
|
|
||||||
impl<T: const send> &rw_write_mode<T> {
|
impl<T: const send> &rw_write_mode<T> {
|
||||||
/// Access the pre-downgrade rw_arc in write mode.
|
/// Access the pre-downgrade rw_arc in write mode.
|
||||||
|
|||||||
@@ -50,6 +50,7 @@ mod cell;
|
|||||||
|
|
||||||
// Concurrency
|
// Concurrency
|
||||||
|
|
||||||
|
#[warn(non_camel_case_types)]
|
||||||
mod sync;
|
mod sync;
|
||||||
mod arc;
|
mod arc;
|
||||||
mod comm;
|
mod comm;
|
||||||
|
|||||||
@@ -8,8 +8,8 @@
|
|||||||
* in std.
|
* in std.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
export condvar, semaphore, mutex, mutex_with_condvars;
|
export Condvar, Semaphore, Mutex, mutex, mutex_with_condvars;
|
||||||
export rwlock, rwlock_with_condvars, rwlock_write_mode, rwlock_read_mode;
|
export RWlock, rwlock, rwlock_with_condvars, RWlockReadMode, RWlockWriteMode;
|
||||||
|
|
||||||
import unsafe::{Exclusive, exclusive};
|
import unsafe::{Exclusive, exclusive};
|
||||||
|
|
||||||
@@ -19,22 +19,22 @@ import unsafe::{Exclusive, exclusive};
|
|||||||
|
|
||||||
// Each waiting task receives on one of these.
|
// Each waiting task receives on one of these.
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
type wait_end = pipes::port_one<()>;
|
type WaitEnd = pipes::port_one<()>;
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
type signal_end = pipes::chan_one<()>;
|
type SignalEnd = pipes::chan_one<()>;
|
||||||
// A doubly-ended queue of waiting tasks.
|
// A doubly-ended queue of waiting tasks.
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
struct waitqueue { head: pipes::port<signal_end>;
|
struct Waitqueue { head: pipes::port<SignalEnd>;
|
||||||
tail: pipes::chan<signal_end>; }
|
tail: pipes::chan<SignalEnd>; }
|
||||||
|
|
||||||
fn new_waitqueue() -> waitqueue {
|
fn new_waitqueue() -> Waitqueue {
|
||||||
let (block_tail, block_head) = pipes::stream();
|
let (block_tail, block_head) = pipes::stream();
|
||||||
waitqueue { head: block_head, tail: block_tail }
|
Waitqueue { head: block_head, tail: block_tail }
|
||||||
}
|
}
|
||||||
|
|
||||||
// Signals one live task from the queue.
|
// Signals one live task from the queue.
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
fn signal_waitqueue(q: &waitqueue) -> bool {
|
fn signal_waitqueue(q: &Waitqueue) -> bool {
|
||||||
// The peek is mandatory to make sure recv doesn't block.
|
// The peek is mandatory to make sure recv doesn't block.
|
||||||
if q.head.peek() {
|
if q.head.peek() {
|
||||||
// Pop and send a wakeup signal. If the waiter was killed, its port
|
// Pop and send a wakeup signal. If the waiter was killed, its port
|
||||||
@@ -50,7 +50,7 @@ fn signal_waitqueue(q: &waitqueue) -> bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
fn broadcast_waitqueue(q: &waitqueue) -> uint {
|
fn broadcast_waitqueue(q: &Waitqueue) -> uint {
|
||||||
let mut count = 0;
|
let mut count = 0;
|
||||||
while q.head.peek() {
|
while q.head.peek() {
|
||||||
if pipes::try_send_one(q.head.recv(), ()) {
|
if pipes::try_send_one(q.head.recv(), ()) {
|
||||||
@@ -62,24 +62,24 @@ fn broadcast_waitqueue(q: &waitqueue) -> uint {
|
|||||||
|
|
||||||
// The building-block used to make semaphores, mutexes, and rwlocks.
|
// The building-block used to make semaphores, mutexes, and rwlocks.
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
struct sem_inner<Q> {
|
struct SemInner<Q> {
|
||||||
mut count: int;
|
mut count: int;
|
||||||
waiters: waitqueue;
|
waiters: Waitqueue;
|
||||||
// Can be either unit or another waitqueue. Some sems shouldn't come with
|
// Can be either unit or another waitqueue. Some sems shouldn't come with
|
||||||
// a condition variable attached, others should.
|
// a condition variable attached, others should.
|
||||||
blocked: Q;
|
blocked: Q;
|
||||||
}
|
}
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
enum sem<Q: send> = Exclusive<sem_inner<Q>>;
|
enum Sem<Q: send> = Exclusive<SemInner<Q>>;
|
||||||
|
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
fn new_sem<Q: send>(count: int, +q: Q) -> sem<Q> {
|
fn new_sem<Q: send>(count: int, +q: Q) -> Sem<Q> {
|
||||||
sem(exclusive(sem_inner {
|
Sem(exclusive(SemInner {
|
||||||
mut count: count, waiters: new_waitqueue(), blocked: q }))
|
mut count: count, waiters: new_waitqueue(), blocked: q }))
|
||||||
}
|
}
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
fn new_sem_and_signal(count: int, num_condvars: uint)
|
fn new_sem_and_signal(count: int, num_condvars: uint)
|
||||||
-> sem<~[mut waitqueue]> {
|
-> Sem<~[mut Waitqueue]> {
|
||||||
let mut queues = ~[mut];
|
let mut queues = ~[mut];
|
||||||
for num_condvars.times {
|
for num_condvars.times {
|
||||||
vec::push(queues, new_waitqueue());
|
vec::push(queues, new_waitqueue());
|
||||||
@@ -88,7 +88,7 @@ fn new_sem_and_signal(count: int, num_condvars: uint)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
impl<Q: send> &sem<Q> {
|
impl<Q: send> &Sem<Q> {
|
||||||
fn acquire() {
|
fn acquire() {
|
||||||
let mut waiter_nobe = None;
|
let mut waiter_nobe = None;
|
||||||
unsafe {
|
unsafe {
|
||||||
@@ -122,28 +122,28 @@ impl<Q: send> &sem<Q> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// FIXME(#3154) move both copies of this into sem<Q>, and unify the 2 structs
|
// FIXME(#3154) move both copies of this into Sem<Q>, and unify the 2 structs
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
impl &sem<()> {
|
impl &Sem<()> {
|
||||||
fn access<U>(blk: fn() -> U) -> U {
|
fn access<U>(blk: fn() -> U) -> U {
|
||||||
let mut release = None;
|
let mut release = None;
|
||||||
unsafe {
|
unsafe {
|
||||||
do task::unkillable {
|
do task::unkillable {
|
||||||
self.acquire();
|
self.acquire();
|
||||||
release = Some(sem_release(self));
|
release = Some(SemRelease(self));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
blk()
|
blk()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
impl &sem<~[mut waitqueue]> {
|
impl &Sem<~[mut Waitqueue]> {
|
||||||
fn access<U>(blk: fn() -> U) -> U {
|
fn access<U>(blk: fn() -> U) -> U {
|
||||||
let mut release = None;
|
let mut release = None;
|
||||||
unsafe {
|
unsafe {
|
||||||
do task::unkillable {
|
do task::unkillable {
|
||||||
self.acquire();
|
self.acquire();
|
||||||
release = Some(sem_and_signal_release(self));
|
release = Some(SemAndSignalRelease(self));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
blk()
|
blk()
|
||||||
@@ -152,22 +152,22 @@ impl &sem<~[mut waitqueue]> {
|
|||||||
|
|
||||||
// FIXME(#3136) should go inside of access()
|
// FIXME(#3136) should go inside of access()
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
struct sem_release {
|
struct SemRelease {
|
||||||
sem: &sem<()>;
|
sem: &Sem<()>;
|
||||||
new(sem: &sem<()>) { self.sem = sem; }
|
new(sem: &Sem<()>) { self.sem = sem; }
|
||||||
drop { self.sem.release(); }
|
drop { self.sem.release(); }
|
||||||
}
|
}
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
struct sem_and_signal_release {
|
struct SemAndSignalRelease {
|
||||||
sem: &sem<~[mut waitqueue]>;
|
sem: &Sem<~[mut Waitqueue]>;
|
||||||
new(sem: &sem<~[mut waitqueue]>) { self.sem = sem; }
|
new(sem: &Sem<~[mut Waitqueue]>) { self.sem = sem; }
|
||||||
drop { self.sem.release(); }
|
drop { self.sem.release(); }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A mechanism for atomic-unlock-and-deschedule blocking and signalling.
|
/// A mechanism for atomic-unlock-and-deschedule blocking and signalling.
|
||||||
struct condvar { priv sem: &sem<~[mut waitqueue]>; drop { } }
|
struct Condvar { priv sem: &Sem<~[mut Waitqueue]>; drop { } }
|
||||||
|
|
||||||
impl &condvar {
|
impl &Condvar {
|
||||||
/**
|
/**
|
||||||
* Atomically drop the associated lock, and block until a signal is sent.
|
* Atomically drop the associated lock, and block until a signal is sent.
|
||||||
*
|
*
|
||||||
@@ -218,7 +218,7 @@ impl &condvar {
|
|||||||
// unkillably reacquire the lock needs to happen atomically
|
// unkillably reacquire the lock needs to happen atomically
|
||||||
// wrt enqueuing.
|
// wrt enqueuing.
|
||||||
if out_of_bounds.is_none() {
|
if out_of_bounds.is_none() {
|
||||||
reacquire = Some(sem_and_signal_reacquire(self.sem));
|
reacquire = Some(SemAndSignalReacquire(self.sem));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -232,9 +232,9 @@ impl &condvar {
|
|||||||
// This is needed for a failing condition variable to reacquire the
|
// This is needed for a failing condition variable to reacquire the
|
||||||
// mutex during unwinding. As long as the wrapper (mutex, etc) is
|
// mutex during unwinding. As long as the wrapper (mutex, etc) is
|
||||||
// bounded in when it gets released, this shouldn't hang forever.
|
// bounded in when it gets released, this shouldn't hang forever.
|
||||||
struct sem_and_signal_reacquire {
|
struct SemAndSignalReacquire {
|
||||||
sem: &sem<~[mut waitqueue]>;
|
sem: &Sem<~[mut Waitqueue]>;
|
||||||
new(sem: &sem<~[mut waitqueue]>) { self.sem = sem; }
|
new(sem: &Sem<~[mut Waitqueue]>) { self.sem = sem; }
|
||||||
drop unsafe {
|
drop unsafe {
|
||||||
// Needs to succeed, instead of itself dying.
|
// Needs to succeed, instead of itself dying.
|
||||||
do task::unkillable {
|
do task::unkillable {
|
||||||
@@ -308,10 +308,10 @@ fn check_cvar_bounds<U>(out_of_bounds: Option<uint>, id: uint, act: &str,
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
impl &sem<~[mut waitqueue]> {
|
impl &Sem<~[mut Waitqueue]> {
|
||||||
// The only other place that condvars get built is rwlock_write_mode.
|
// The only other place that condvars get built is rwlock_write_mode.
|
||||||
fn access_cond<U>(blk: fn(c: &condvar) -> U) -> U {
|
fn access_cond<U>(blk: fn(c: &Condvar) -> U) -> U {
|
||||||
do self.access { blk(&condvar { sem: self }) }
|
do self.access { blk(&Condvar { sem: self }) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -320,16 +320,16 @@ impl &sem<~[mut waitqueue]> {
|
|||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
/// A counting, blocking, bounded-waiting semaphore.
|
/// A counting, blocking, bounded-waiting semaphore.
|
||||||
struct semaphore { priv sem: sem<()>; }
|
struct Semaphore { priv sem: Sem<()>; }
|
||||||
|
|
||||||
/// Create a new semaphore with the specified count.
|
/// Create a new semaphore with the specified count.
|
||||||
fn semaphore(count: int) -> semaphore {
|
fn semaphore(count: int) -> Semaphore {
|
||||||
semaphore { sem: new_sem(count, ()) }
|
Semaphore { sem: new_sem(count, ()) }
|
||||||
}
|
}
|
||||||
|
|
||||||
impl &semaphore {
|
impl &Semaphore {
|
||||||
/// Create a new handle to the semaphore.
|
/// Create a new handle to the semaphore.
|
||||||
fn clone() -> semaphore { semaphore { sem: sem((*self.sem).clone()) } }
|
fn clone() -> Semaphore { Semaphore { sem: Sem((*self.sem).clone()) } }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Acquire a resource represented by the semaphore. Blocks if necessary
|
* Acquire a resource represented by the semaphore. Blocks if necessary
|
||||||
@@ -359,29 +359,29 @@ impl &semaphore {
|
|||||||
* A task which fails while holding a mutex will unlock the mutex as it
|
* A task which fails while holding a mutex will unlock the mutex as it
|
||||||
* unwinds.
|
* unwinds.
|
||||||
*/
|
*/
|
||||||
struct mutex { priv sem: sem<~[mut waitqueue]>; }
|
struct Mutex { priv sem: Sem<~[mut Waitqueue]>; }
|
||||||
|
|
||||||
/// Create a new mutex, with one associated condvar.
|
/// Create a new mutex, with one associated condvar.
|
||||||
fn mutex() -> mutex { mutex_with_condvars(1) }
|
fn mutex() -> Mutex { mutex_with_condvars(1) }
|
||||||
/**
|
/**
|
||||||
* Create a new mutex, with a specified number of associated condvars. This
|
* Create a new mutex, with a specified number of associated condvars. This
|
||||||
* will allow calling wait_on/signal_on/broadcast_on with condvar IDs between
|
* will allow calling wait_on/signal_on/broadcast_on with condvar IDs between
|
||||||
* 0 and num_condvars-1. (If num_condvars is 0, lock_cond will be allowed but
|
* 0 and num_condvars-1. (If num_condvars is 0, lock_cond will be allowed but
|
||||||
* any operations on the condvar will fail.)
|
* any operations on the condvar will fail.)
|
||||||
*/
|
*/
|
||||||
fn mutex_with_condvars(num_condvars: uint) -> mutex {
|
fn mutex_with_condvars(num_condvars: uint) -> Mutex {
|
||||||
mutex { sem: new_sem_and_signal(1, num_condvars) }
|
Mutex { sem: new_sem_and_signal(1, num_condvars) }
|
||||||
}
|
}
|
||||||
|
|
||||||
impl &mutex {
|
impl &Mutex {
|
||||||
/// Create a new handle to the mutex.
|
/// Create a new handle to the mutex.
|
||||||
fn clone() -> mutex { mutex { sem: sem((*self.sem).clone()) } }
|
fn clone() -> Mutex { Mutex { sem: Sem((*self.sem).clone()) } }
|
||||||
|
|
||||||
/// Run a function with ownership of the mutex.
|
/// Run a function with ownership of the mutex.
|
||||||
fn lock<U>(blk: fn() -> U) -> U { (&self.sem).access(blk) }
|
fn lock<U>(blk: fn() -> U) -> U { (&self.sem).access(blk) }
|
||||||
|
|
||||||
/// Run a function with ownership of the mutex and a handle to a condvar.
|
/// Run a function with ownership of the mutex and a handle to a condvar.
|
||||||
fn lock_cond<U>(blk: fn(c: &condvar) -> U) -> U {
|
fn lock_cond<U>(blk: fn(c: &Condvar) -> U) -> U {
|
||||||
(&self.sem).access_cond(blk)
|
(&self.sem).access_cond(blk)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -393,7 +393,7 @@ impl &mutex {
|
|||||||
// NB: Wikipedia - Readers-writers_problem#The_third_readers-writers_problem
|
// NB: Wikipedia - Readers-writers_problem#The_third_readers-writers_problem
|
||||||
|
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
struct rwlock_inner {
|
struct RWlockInner {
|
||||||
read_mode: bool;
|
read_mode: bool;
|
||||||
read_count: uint;
|
read_count: uint;
|
||||||
}
|
}
|
||||||
@@ -405,31 +405,31 @@ struct rwlock_inner {
|
|||||||
* A task which fails while holding an rwlock will unlock the rwlock as it
|
* A task which fails while holding an rwlock will unlock the rwlock as it
|
||||||
* unwinds.
|
* unwinds.
|
||||||
*/
|
*/
|
||||||
struct rwlock {
|
struct RWlock {
|
||||||
/* priv */ order_lock: semaphore;
|
/* priv */ order_lock: Semaphore;
|
||||||
/* priv */ access_lock: sem<~[mut waitqueue]>;
|
/* priv */ access_lock: Sem<~[mut Waitqueue]>;
|
||||||
/* priv */ state: Exclusive<rwlock_inner>;
|
/* priv */ state: Exclusive<RWlockInner>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a new rwlock, with one associated condvar.
|
/// Create a new rwlock, with one associated condvar.
|
||||||
fn rwlock() -> rwlock { rwlock_with_condvars(1) }
|
fn rwlock() -> RWlock { rwlock_with_condvars(1) }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new rwlock, with a specified number of associated condvars.
|
* Create a new rwlock, with a specified number of associated condvars.
|
||||||
* Similar to mutex_with_condvars.
|
* Similar to mutex_with_condvars.
|
||||||
*/
|
*/
|
||||||
fn rwlock_with_condvars(num_condvars: uint) -> rwlock {
|
fn rwlock_with_condvars(num_condvars: uint) -> RWlock {
|
||||||
rwlock { order_lock: semaphore(1),
|
RWlock { order_lock: semaphore(1),
|
||||||
access_lock: new_sem_and_signal(1, num_condvars),
|
access_lock: new_sem_and_signal(1, num_condvars),
|
||||||
state: exclusive(rwlock_inner { read_mode: false,
|
state: exclusive(RWlockInner { read_mode: false,
|
||||||
read_count: 0 }) }
|
read_count: 0 }) }
|
||||||
}
|
}
|
||||||
|
|
||||||
impl &rwlock {
|
impl &RWlock {
|
||||||
/// Create a new handle to the rwlock.
|
/// Create a new handle to the rwlock.
|
||||||
fn clone() -> rwlock {
|
fn clone() -> RWlock {
|
||||||
rwlock { order_lock: (&(self.order_lock)).clone(),
|
RWlock { order_lock: (&(self.order_lock)).clone(),
|
||||||
access_lock: sem((*self.access_lock).clone()),
|
access_lock: Sem((*self.access_lock).clone()),
|
||||||
state: self.state.clone() }
|
state: self.state.clone() }
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -458,7 +458,7 @@ impl &rwlock {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
release = Some(rwlock_release_read(self));
|
release = Some(RWlockReleaseRead(self));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
blk()
|
blk()
|
||||||
@@ -486,7 +486,7 @@ impl &rwlock {
|
|||||||
* the waiting task is signalled. (Note: a writer that waited and then
|
* the waiting task is signalled. (Note: a writer that waited and then
|
||||||
* was signalled might reacquire the lock before other waiting writers.)
|
* was signalled might reacquire the lock before other waiting writers.)
|
||||||
*/
|
*/
|
||||||
fn write_cond<U>(blk: fn(c: &condvar) -> U) -> U {
|
fn write_cond<U>(blk: fn(c: &Condvar) -> U) -> U {
|
||||||
// NB: You might think I should thread the order_lock into the cond
|
// NB: You might think I should thread the order_lock into the cond
|
||||||
// wait call, so that it gets waited on before access_lock gets
|
// wait call, so that it gets waited on before access_lock gets
|
||||||
// reacquired upon being woken up. However, (a) this would be not
|
// reacquired upon being woken up. However, (a) this would be not
|
||||||
@@ -521,7 +521,7 @@ impl &rwlock {
|
|||||||
* }
|
* }
|
||||||
* ~~~
|
* ~~~
|
||||||
*/
|
*/
|
||||||
fn write_downgrade<U>(blk: fn(+rwlock_write_mode) -> U) -> U {
|
fn write_downgrade<U>(blk: fn(+RWlockWriteMode) -> U) -> U {
|
||||||
// Implementation slightly different from the slicker 'write's above.
|
// Implementation slightly different from the slicker 'write's above.
|
||||||
// The exit path is conditional on whether the caller downgrades.
|
// The exit path is conditional on whether the caller downgrades.
|
||||||
let mut _release = None;
|
let mut _release = None;
|
||||||
@@ -531,13 +531,13 @@ impl &rwlock {
|
|||||||
(&self.access_lock).acquire();
|
(&self.access_lock).acquire();
|
||||||
(&self.order_lock).release();
|
(&self.order_lock).release();
|
||||||
}
|
}
|
||||||
_release = Some(rwlock_release_downgrade(self));
|
_release = Some(RWlockReleaseDowngrade(self));
|
||||||
}
|
}
|
||||||
blk(rwlock_write_mode { lock: self })
|
blk(RWlockWriteMode { lock: self })
|
||||||
}
|
}
|
||||||
|
|
||||||
/// To be called inside of the write_downgrade block.
|
/// To be called inside of the write_downgrade block.
|
||||||
fn downgrade(+token: rwlock_write_mode/&a) -> rwlock_read_mode/&a {
|
fn downgrade(+token: RWlockWriteMode/&a) -> RWlockReadMode/&a {
|
||||||
if !ptr::ref_eq(self, token.lock) {
|
if !ptr::ref_eq(self, token.lock) {
|
||||||
fail ~"Can't downgrade() with a different rwlock's write_mode!";
|
fail ~"Can't downgrade() with a different rwlock's write_mode!";
|
||||||
}
|
}
|
||||||
@@ -559,15 +559,15 @@ impl &rwlock {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
rwlock_read_mode { lock: token.lock }
|
RWlockReadMode { lock: token.lock }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME(#3136) should go inside of read()
|
// FIXME(#3136) should go inside of read()
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
struct rwlock_release_read {
|
struct RWlockReleaseRead {
|
||||||
lock: &rwlock;
|
lock: &RWlock;
|
||||||
new(lock: &rwlock) { self.lock = lock; }
|
new(lock: &RWlock) { self.lock = lock; }
|
||||||
drop unsafe {
|
drop unsafe {
|
||||||
do task::unkillable {
|
do task::unkillable {
|
||||||
let mut last_reader = false;
|
let mut last_reader = false;
|
||||||
@@ -589,9 +589,9 @@ struct rwlock_release_read {
|
|||||||
|
|
||||||
// FIXME(#3136) should go inside of downgrade()
|
// FIXME(#3136) should go inside of downgrade()
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
struct rwlock_release_downgrade {
|
struct RWlockReleaseDowngrade {
|
||||||
lock: &rwlock;
|
lock: &RWlock;
|
||||||
new(lock: &rwlock) { self.lock = lock; }
|
new(lock: &RWlock) { self.lock = lock; }
|
||||||
drop unsafe {
|
drop unsafe {
|
||||||
do task::unkillable {
|
do task::unkillable {
|
||||||
let mut writer_or_last_reader = false;
|
let mut writer_or_last_reader = false;
|
||||||
@@ -619,19 +619,19 @@ struct rwlock_release_downgrade {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// The "write permission" token used for rwlock.write_downgrade().
|
/// The "write permission" token used for rwlock.write_downgrade().
|
||||||
struct rwlock_write_mode { /* priv */ lock: &rwlock; drop { } }
|
struct RWlockWriteMode { /* priv */ lock: &RWlock; drop { } }
|
||||||
/// The "read permission" token used for rwlock.write_downgrade().
|
/// The "read permission" token used for rwlock.write_downgrade().
|
||||||
struct rwlock_read_mode { priv lock: &rwlock; drop { } }
|
struct RWlockReadMode { priv lock: &RWlock; drop { } }
|
||||||
|
|
||||||
impl &rwlock_write_mode {
|
impl &RWlockWriteMode {
|
||||||
/// Access the pre-downgrade rwlock in write mode.
|
/// Access the pre-downgrade rwlock in write mode.
|
||||||
fn write<U>(blk: fn() -> U) -> U { blk() }
|
fn write<U>(blk: fn() -> U) -> U { blk() }
|
||||||
/// Access the pre-downgrade rwlock in write mode with a condvar.
|
/// Access the pre-downgrade rwlock in write mode with a condvar.
|
||||||
fn write_cond<U>(blk: fn(c: &condvar) -> U) -> U {
|
fn write_cond<U>(blk: fn(c: &Condvar) -> U) -> U {
|
||||||
blk(&condvar { sem: &self.lock.access_lock })
|
blk(&Condvar { sem: &self.lock.access_lock })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl &rwlock_read_mode {
|
impl &RWlockReadMode {
|
||||||
/// Access the post-downgrade rwlock in read mode.
|
/// Access the post-downgrade rwlock in read mode.
|
||||||
fn read<U>(blk: fn() -> U) -> U { blk() }
|
fn read<U>(blk: fn() -> U) -> U { blk() }
|
||||||
}
|
}
|
||||||
@@ -761,7 +761,7 @@ mod tests {
|
|||||||
|
|
||||||
assert *sharedstate == 20;
|
assert *sharedstate == 20;
|
||||||
|
|
||||||
fn access_shared(sharedstate: &mut int, m: &mutex, n: uint) {
|
fn access_shared(sharedstate: &mut int, m: &Mutex, n: uint) {
|
||||||
for n.times {
|
for n.times {
|
||||||
do m.lock {
|
do m.lock {
|
||||||
let oldval = *sharedstate;
|
let oldval = *sharedstate;
|
||||||
@@ -908,7 +908,7 @@ mod tests {
|
|||||||
do mi.lock_cond |cond| {
|
do mi.lock_cond |cond| {
|
||||||
let c = option::swap_unwrap(c);
|
let c = option::swap_unwrap(c);
|
||||||
c.send(()); // tell sibling to go ahead
|
c.send(()); // tell sibling to go ahead
|
||||||
let _z = send_on_failure(c);
|
let _z = SendOnFailure(c);
|
||||||
cond.wait(); // block forever
|
cond.wait(); // block forever
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -927,7 +927,7 @@ mod tests {
|
|||||||
let woken = cond.broadcast();
|
let woken = cond.broadcast();
|
||||||
assert woken == 0;
|
assert woken == 0;
|
||||||
}
|
}
|
||||||
struct send_on_failure {
|
struct SendOnFailure {
|
||||||
c: pipes::chan<()>;
|
c: pipes::chan<()>;
|
||||||
new(+c: pipes::chan<()>) { self.c = c; }
|
new(+c: pipes::chan<()>) { self.c = c; }
|
||||||
drop { self.c.send(()); }
|
drop { self.c.send(()); }
|
||||||
@@ -990,17 +990,17 @@ mod tests {
|
|||||||
* Reader/writer lock tests
|
* Reader/writer lock tests
|
||||||
************************************************************************/
|
************************************************************************/
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
enum rwlock_mode { read, write, downgrade, downgrade_read }
|
enum RWlockMode { Read, Write, Downgrade, DowngradeRead }
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
fn lock_rwlock_in_mode(x: &rwlock, mode: rwlock_mode, blk: fn()) {
|
fn lock_rwlock_in_mode(x: &RWlock, mode: RWlockMode, blk: fn()) {
|
||||||
match mode {
|
match mode {
|
||||||
read => x.read(blk),
|
Read => x.read(blk),
|
||||||
write => x.write(blk),
|
Write => x.write(blk),
|
||||||
downgrade =>
|
Downgrade =>
|
||||||
do x.write_downgrade |mode| {
|
do x.write_downgrade |mode| {
|
||||||
(&mode).write(blk);
|
(&mode).write(blk);
|
||||||
},
|
},
|
||||||
downgrade_read =>
|
DowngradeRead =>
|
||||||
do x.write_downgrade |mode| {
|
do x.write_downgrade |mode| {
|
||||||
let mode = x.downgrade(mode);
|
let mode = x.downgrade(mode);
|
||||||
(&mode).read(blk);
|
(&mode).read(blk);
|
||||||
@@ -1008,8 +1008,8 @@ mod tests {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
fn test_rwlock_exclusion(+x: ~rwlock, mode1: rwlock_mode,
|
fn test_rwlock_exclusion(+x: ~RWlock, mode1: RWlockMode,
|
||||||
mode2: rwlock_mode) {
|
mode2: RWlockMode) {
|
||||||
// Test mutual exclusion between readers and writers. Just like the
|
// Test mutual exclusion between readers and writers. Just like the
|
||||||
// mutex mutual exclusion test, a ways above.
|
// mutex mutual exclusion test, a ways above.
|
||||||
let (c,p) = pipes::stream();
|
let (c,p) = pipes::stream();
|
||||||
@@ -1027,7 +1027,7 @@ mod tests {
|
|||||||
|
|
||||||
assert *sharedstate == 20;
|
assert *sharedstate == 20;
|
||||||
|
|
||||||
fn access_shared(sharedstate: &mut int, x: &rwlock, mode: rwlock_mode,
|
fn access_shared(sharedstate: &mut int, x: &RWlock, mode: RWlockMode,
|
||||||
n: uint) {
|
n: uint) {
|
||||||
for n.times {
|
for n.times {
|
||||||
do lock_rwlock_in_mode(x, mode) {
|
do lock_rwlock_in_mode(x, mode) {
|
||||||
@@ -1040,21 +1040,21 @@ mod tests {
|
|||||||
}
|
}
|
||||||
#[test]
|
#[test]
|
||||||
fn test_rwlock_readers_wont_modify_the_data() {
|
fn test_rwlock_readers_wont_modify_the_data() {
|
||||||
test_rwlock_exclusion(~rwlock(), read, write);
|
test_rwlock_exclusion(~rwlock(), Read, Write);
|
||||||
test_rwlock_exclusion(~rwlock(), write, read);
|
test_rwlock_exclusion(~rwlock(), Write, Read);
|
||||||
test_rwlock_exclusion(~rwlock(), read, downgrade);
|
test_rwlock_exclusion(~rwlock(), Read, Downgrade);
|
||||||
test_rwlock_exclusion(~rwlock(), downgrade, read);
|
test_rwlock_exclusion(~rwlock(), Downgrade, Read);
|
||||||
}
|
}
|
||||||
#[test]
|
#[test]
|
||||||
fn test_rwlock_writers_and_writers() {
|
fn test_rwlock_writers_and_writers() {
|
||||||
test_rwlock_exclusion(~rwlock(), write, write);
|
test_rwlock_exclusion(~rwlock(), Write, Write);
|
||||||
test_rwlock_exclusion(~rwlock(), write, downgrade);
|
test_rwlock_exclusion(~rwlock(), Write, Downgrade);
|
||||||
test_rwlock_exclusion(~rwlock(), downgrade, write);
|
test_rwlock_exclusion(~rwlock(), Downgrade, Write);
|
||||||
test_rwlock_exclusion(~rwlock(), downgrade, downgrade);
|
test_rwlock_exclusion(~rwlock(), Downgrade, Downgrade);
|
||||||
}
|
}
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
fn test_rwlock_handshake(+x: ~rwlock, mode1: rwlock_mode,
|
fn test_rwlock_handshake(+x: ~RWlock, mode1: RWlockMode,
|
||||||
mode2: rwlock_mode, make_mode2_go_first: bool) {
|
mode2: RWlockMode, make_mode2_go_first: bool) {
|
||||||
// Much like sem_multi_resource.
|
// Much like sem_multi_resource.
|
||||||
let x2 = ~x.clone();
|
let x2 = ~x.clone();
|
||||||
let (c1,p1) = pipes::stream();
|
let (c1,p1) = pipes::stream();
|
||||||
@@ -1084,22 +1084,22 @@ mod tests {
|
|||||||
}
|
}
|
||||||
#[test]
|
#[test]
|
||||||
fn test_rwlock_readers_and_readers() {
|
fn test_rwlock_readers_and_readers() {
|
||||||
test_rwlock_handshake(~rwlock(), read, read, false);
|
test_rwlock_handshake(~rwlock(), Read, Read, false);
|
||||||
// The downgrader needs to get in before the reader gets in, otherwise
|
// The downgrader needs to get in before the reader gets in, otherwise
|
||||||
// they cannot end up reading at the same time.
|
// they cannot end up reading at the same time.
|
||||||
test_rwlock_handshake(~rwlock(), downgrade_read, read, false);
|
test_rwlock_handshake(~rwlock(), DowngradeRead, Read, false);
|
||||||
test_rwlock_handshake(~rwlock(), read, downgrade_read, true);
|
test_rwlock_handshake(~rwlock(), Read, DowngradeRead, true);
|
||||||
// Two downgrade_reads can never both end up reading at the same time.
|
// Two downgrade_reads can never both end up reading at the same time.
|
||||||
}
|
}
|
||||||
#[test]
|
#[test]
|
||||||
fn test_rwlock_downgrade_unlock() {
|
fn test_rwlock_downgrade_unlock() {
|
||||||
// Tests that downgrade can unlock the lock in both modes
|
// Tests that downgrade can unlock the lock in both modes
|
||||||
let x = ~rwlock();
|
let x = ~rwlock();
|
||||||
do lock_rwlock_in_mode(x, downgrade) { }
|
do lock_rwlock_in_mode(x, Downgrade) { }
|
||||||
test_rwlock_handshake(x, read, read, false);
|
test_rwlock_handshake(x, Read, Read, false);
|
||||||
let y = ~rwlock();
|
let y = ~rwlock();
|
||||||
do lock_rwlock_in_mode(y, downgrade_read) { }
|
do lock_rwlock_in_mode(y, DowngradeRead) { }
|
||||||
test_rwlock_exclusion(y, write, write);
|
test_rwlock_exclusion(y, Write, Write);
|
||||||
}
|
}
|
||||||
#[test]
|
#[test]
|
||||||
fn test_rwlock_read_recursive() {
|
fn test_rwlock_read_recursive() {
|
||||||
@@ -1145,7 +1145,7 @@ mod tests {
|
|||||||
fn test_rwlock_cond_broadcast_helper(num_waiters: uint, dg1: bool,
|
fn test_rwlock_cond_broadcast_helper(num_waiters: uint, dg1: bool,
|
||||||
dg2: bool) {
|
dg2: bool) {
|
||||||
// Much like the mutex broadcast test. Downgrade-enabled.
|
// Much like the mutex broadcast test. Downgrade-enabled.
|
||||||
fn lock_cond(x: &rwlock, downgrade: bool, blk: fn(c: &condvar)) {
|
fn lock_cond(x: &RWlock, downgrade: bool, blk: fn(c: &Condvar)) {
|
||||||
if downgrade {
|
if downgrade {
|
||||||
do x.write_downgrade |mode| {
|
do x.write_downgrade |mode| {
|
||||||
(&mode).write_cond(blk)
|
(&mode).write_cond(blk)
|
||||||
@@ -1191,7 +1191,7 @@ mod tests {
|
|||||||
test_rwlock_cond_broadcast_helper(12, false, false);
|
test_rwlock_cond_broadcast_helper(12, false, false);
|
||||||
}
|
}
|
||||||
#[cfg(test)] #[ignore(cfg(windows))]
|
#[cfg(test)] #[ignore(cfg(windows))]
|
||||||
fn rwlock_kill_helper(mode1: rwlock_mode, mode2: rwlock_mode) {
|
fn rwlock_kill_helper(mode1: RWlockMode, mode2: RWlockMode) {
|
||||||
// Mutex must get automatically unlocked if failed/killed within.
|
// Mutex must get automatically unlocked if failed/killed within.
|
||||||
let x = ~rwlock();
|
let x = ~rwlock();
|
||||||
let x2 = ~x.clone();
|
let x2 = ~x.clone();
|
||||||
@@ -1206,27 +1206,27 @@ mod tests {
|
|||||||
do lock_rwlock_in_mode(x, mode2) { }
|
do lock_rwlock_in_mode(x, mode2) { }
|
||||||
}
|
}
|
||||||
#[test] #[ignore(cfg(windows))]
|
#[test] #[ignore(cfg(windows))]
|
||||||
fn test_rwlock_reader_killed_writer() { rwlock_kill_helper(read, write); }
|
fn test_rwlock_reader_killed_writer() { rwlock_kill_helper(Read, Write); }
|
||||||
#[test] #[ignore(cfg(windows))]
|
#[test] #[ignore(cfg(windows))]
|
||||||
fn test_rwlock_writer_killed_reader() { rwlock_kill_helper(write,read ); }
|
fn test_rwlock_writer_killed_reader() { rwlock_kill_helper(Write,Read ); }
|
||||||
#[test] #[ignore(cfg(windows))]
|
#[test] #[ignore(cfg(windows))]
|
||||||
fn test_rwlock_reader_killed_reader() { rwlock_kill_helper(read, read ); }
|
fn test_rwlock_reader_killed_reader() { rwlock_kill_helper(Read, Read ); }
|
||||||
#[test] #[ignore(cfg(windows))]
|
#[test] #[ignore(cfg(windows))]
|
||||||
fn test_rwlock_writer_killed_writer() { rwlock_kill_helper(write,write); }
|
fn test_rwlock_writer_killed_writer() { rwlock_kill_helper(Write,Write); }
|
||||||
#[test] #[ignore(cfg(windows))]
|
#[test] #[ignore(cfg(windows))]
|
||||||
fn test_rwlock_kill_downgrader() {
|
fn test_rwlock_kill_downgrader() {
|
||||||
rwlock_kill_helper(downgrade, read);
|
rwlock_kill_helper(Downgrade, Read);
|
||||||
rwlock_kill_helper(read, downgrade);
|
rwlock_kill_helper(Read, Downgrade);
|
||||||
rwlock_kill_helper(downgrade, write);
|
rwlock_kill_helper(Downgrade, Write);
|
||||||
rwlock_kill_helper(write, downgrade);
|
rwlock_kill_helper(Write, Downgrade);
|
||||||
rwlock_kill_helper(downgrade_read, read);
|
rwlock_kill_helper(DowngradeRead, Read);
|
||||||
rwlock_kill_helper(read, downgrade_read);
|
rwlock_kill_helper(Read, DowngradeRead);
|
||||||
rwlock_kill_helper(downgrade_read, write);
|
rwlock_kill_helper(DowngradeRead, Write);
|
||||||
rwlock_kill_helper(write, downgrade_read);
|
rwlock_kill_helper(Write, DowngradeRead);
|
||||||
rwlock_kill_helper(downgrade_read, downgrade);
|
rwlock_kill_helper(DowngradeRead, Downgrade);
|
||||||
rwlock_kill_helper(downgrade_read, downgrade);
|
rwlock_kill_helper(DowngradeRead, Downgrade);
|
||||||
rwlock_kill_helper(downgrade, downgrade_read);
|
rwlock_kill_helper(Downgrade, DowngradeRead);
|
||||||
rwlock_kill_helper(downgrade, downgrade_read);
|
rwlock_kill_helper(Downgrade, DowngradeRead);
|
||||||
}
|
}
|
||||||
#[test] #[should_fail] #[ignore(cfg(windows))]
|
#[test] #[should_fail] #[ignore(cfg(windows))]
|
||||||
fn test_rwlock_downgrade_cant_swap() {
|
fn test_rwlock_downgrade_cant_swap() {
|
||||||
|
|||||||
Reference in New Issue
Block a user