From f29f308c1c7c611cda6e1fc8a56179296868d144 Mon Sep 17 00:00:00 2001 From: Ben Blum Date: Tue, 14 Aug 2012 23:35:12 -0400 Subject: [PATCH] Enable multiple condvars on a single mutex_arc/rw_arc. --- src/libstd/arc.rs | 68 ++++++++++++++++++++++++++++++++++++---------- src/libstd/sync.rs | 3 +- 2 files changed, 56 insertions(+), 15 deletions(-) diff --git a/src/libstd/arc.rs b/src/libstd/arc.rs index 8d6c7ce5d29..600bf45c465 100644 --- a/src/libstd/arc.rs +++ b/src/libstd/arc.rs @@ -10,31 +10,55 @@ import unsafe::{SharedMutableState, shared_mutable_state, clone_shared_mutable_state, get_shared_mutable_state, get_shared_immutable_state}; import sync; -import sync::{mutex, rwlock}; +import sync::{mutex, mutex_with_condvars, rwlock, rwlock_with_condvars}; export arc, clone, get; -export condvar, mutex_arc, rw_arc, rw_write_mode, rw_read_mode; +export condvar, mutex_arc, mutex_arc_with_condvars; +export rw_arc, rw_arc_with_condvars, rw_write_mode, rw_read_mode; /// As sync::condvar, a mechanism for unlock-and-descheduling and signalling. struct condvar { is_mutex: bool; failed: &mut bool; cond: &sync::condvar; } impl &condvar { /// Atomically exit the associated ARC and block until a signal is sent. - fn wait() { + #[inline(always)] + fn wait() { self.wait_on(0) } + /** + * Atomically exit the associated ARC and block on a specified condvar + * until a signal is sent on that same condvar (as sync::cond.wait_on). + * + * wait() is equivalent to wait_on(0). + */ + #[inline(always)] + fn wait_on(condvar_id: uint) { assert !*self.failed; - self.cond.wait(); + self.cond.wait_on(condvar_id); // This is why we need to wrap sync::condvar. check_poison(self.is_mutex, *self.failed); } /// Wake up a blocked task. Returns false if there was no blocked task. - fn signal() -> bool { + #[inline(always)] + fn signal() -> bool { self.signal_on(0) } + /** + * Wake up a blocked task on a specified condvar (as + * sync::cond.signal_on). Returns false if there was no blocked task. + */ + #[inline(always)] + fn signal_on(condvar_id: uint) -> bool { assert !*self.failed; - self.cond.signal() + self.cond.signal_on(condvar_id) } /// Wake up all blocked tasks. Returns the number of tasks woken. - fn broadcast() -> uint { + #[inline(always)] + fn broadcast() -> uint { self.broadcast_on(0) } + /** + * Wake up all blocked tasks on a specified condvar (as + * sync::cond.broadcast_on). Returns Returns the number of tasks woken. + */ + #[inline(always)] + fn broadcast_on(condvar_id: uint) -> uint { assert !*self.failed; - self.cond.broadcast() + self.cond.broadcast_on(condvar_id) } } @@ -79,9 +103,17 @@ struct mutex_arc { x: SharedMutableState>; } /// Create a mutex-protected ARC with the supplied data. fn mutex_arc(+user_data: T) -> mutex_arc { - let data = mutex_arc_inner { - lock: mutex(), failed: false, data: user_data - }; + mutex_arc_with_condvars(user_data, 1) +} +/** + * Create a mutex-protected ARC with the supplied data and a specified number + * of condvars (as sync::mutex_with_condvars). + */ +fn mutex_arc_with_condvars(+user_data: T, + num_condvars: uint) -> mutex_arc { + let data = + mutex_arc_inner { lock: mutex_with_condvars(num_condvars), + failed: false, data: user_data }; mutex_arc { x: unsafe { shared_mutable_state(data) } } } @@ -187,9 +219,17 @@ struct rw_arc { /// Create a reader/writer ARC with the supplied data. fn rw_arc(+user_data: T) -> rw_arc { - let data = rw_arc_inner { - lock: rwlock(), failed: false, data: user_data - }; + rw_arc_with_condvars(user_data, 1) +} +/** + * Create a reader/writer ARC with the supplied data and a specified number + * of condvars (as sync::rwlock_with_condvars). + */ +fn rw_arc_with_condvars(+user_data: T, + num_condvars: uint) -> rw_arc { + let data = + rw_arc_inner { lock: rwlock_with_condvars(num_condvars), + failed: false, data: user_data }; rw_arc { x: unsafe { shared_mutable_state(data) }, cant_nest: () } } diff --git a/src/libstd/sync.rs b/src/libstd/sync.rs index c8a16b58d32..c8931eb8d0d 100644 --- a/src/libstd/sync.rs +++ b/src/libstd/sync.rs @@ -8,7 +8,8 @@ * in std. */ -export condvar, semaphore, mutex, rwlock, rwlock_write_mode, rwlock_read_mode; +export condvar, semaphore, mutex, mutex_with_condvars; +export rwlock, rwlock_with_condvars, rwlock_write_mode, rwlock_read_mode; // FIXME (#3119) This shouldn't be a thing exported from core. import unsafe::{Exclusive, exclusive};