From 76a59fd6e2d5c8c42193c047fd5eaba982d499f7 Mon Sep 17 00:00:00 2001 From: Huon Wilson Date: Thu, 13 Feb 2014 17:17:50 +1100 Subject: std: add an RAII unlocker to Mutex. This automatically unlocks its lock when it goes out of scope, and provides a safe(ish) method to call .wait. --- src/libsync/sync/mutex.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/libsync') diff --git a/src/libsync/sync/mutex.rs b/src/libsync/sync/mutex.rs index 3726528a5e9..f5914b26e85 100644 --- a/src/libsync/sync/mutex.rs +++ b/src/libsync/sync/mutex.rs @@ -288,11 +288,11 @@ impl StaticMutex { // `lock()` function on an OS mutex fn native_lock(&mut self, t: ~Task) { Local::put(t); - unsafe { self.lock.lock(); } + unsafe { self.lock.lock_noguard(); } } fn native_unlock(&mut self) { - unsafe { self.lock.unlock(); } + unsafe { self.lock.unlock_noguard(); } } fn green_lock(&mut self, t: ~Task) { -- cgit 1.4.1-3-g733a5 From b87ed605c0ef27f5532ec30c92128bd890de5955 Mon Sep 17 00:00:00 2001 From: Huon Wilson Date: Sat, 15 Feb 2014 11:18:49 +1100 Subject: std: Rename unstable::mutex::Mutex to StaticNativeMutex. This better reflects its purpose and design. --- src/libgreen/sched.rs | 8 ++--- src/libgreen/task.rs | 8 ++--- src/libnative/bookkeeping.rs | 4 +-- src/libnative/io/net.rs | 4 +-- src/libnative/io/timer_helper.rs | 4 +-- src/libnative/task.rs | 6 ++-- src/libstd/comm/shared.rs | 6 ++-- src/libstd/os.rs | 4 +-- src/libstd/rt/args.rs | 4 +-- src/libstd/unstable/dynamic_lib.rs | 4 +-- src/libstd/unstable/mutex.rs | 70 ++++++++++++++++++++------------------ src/libstd/unstable/sync.rs | 6 ++-- src/libsync/sync/mutex.rs | 6 ++-- 13 files changed, 69 insertions(+), 65 deletions(-) (limited to 'src/libsync') diff --git a/src/libgreen/sched.rs b/src/libgreen/sched.rs index 0e8d8ef88e8..bf6a6d54220 100644 --- a/src/libgreen/sched.rs +++ b/src/libgreen/sched.rs @@ -15,7 +15,7 @@ use std::rt::rtio::{RemoteCallback, PausableIdleCallback, Callback, EventLoop}; use std::rt::task::BlockedTask; use std::rt::task::Task; use std::sync::deque; -use std::unstable::mutex::Mutex; +use std::unstable::mutex::StaticNativeMutex; use std::unstable::raw; use TaskState; @@ -764,7 +764,7 @@ impl Scheduler { // to it, but we're guaranteed that the task won't exit until we've // unlocked the lock so there's no worry of this memory going away. let cur = self.change_task_context(cur, next, |sched, mut task| { - let lock: *mut Mutex = &mut task.nasty_deschedule_lock; + let lock: *mut StaticNativeMutex = &mut task.nasty_deschedule_lock; unsafe { let _guard = (*lock).lock(); f(sched, BlockedTask::block(task.swap())); @@ -1453,8 +1453,8 @@ mod test { #[test] fn test_spawn_sched_blocking() { - use std::unstable::mutex::{Mutex, MUTEX_INIT}; - static mut LOCK: Mutex = MUTEX_INIT; + use std::unstable::mutex::{StaticNativeMutex, NATIVE_MUTEX_INIT}; + static mut LOCK: StaticNativeMutex = NATIVE_MUTEX_INIT; // Testing that a task in one scheduler can block in foreign code // without affecting other schedulers diff --git a/src/libgreen/task.rs b/src/libgreen/task.rs index 455f7e589e4..c0c0ef3e24f 100644 --- a/src/libgreen/task.rs +++ b/src/libgreen/task.rs @@ -25,7 +25,7 @@ use std::rt::local::Local; use std::rt::rtio; use std::rt::task::{Task, BlockedTask, SendMessage}; use std::task::TaskOpts; -use std::unstable::mutex::Mutex; +use std::unstable::mutex::StaticNativeMutex; use std::unstable::raw; use context::Context; @@ -65,7 +65,7 @@ pub struct GreenTask { pool_id: uint, // See the comments in the scheduler about why this is necessary - nasty_deschedule_lock: Mutex, + nasty_deschedule_lock: StaticNativeMutex, } pub enum TaskType { @@ -163,7 +163,7 @@ impl GreenTask { task_type: task_type, sched: None, handle: None, - nasty_deschedule_lock: unsafe { Mutex::new() }, + nasty_deschedule_lock: unsafe { StaticNativeMutex::new() }, task: Some(~Task::new()), } } @@ -322,7 +322,7 @@ impl GreenTask { // uncontended except for when the task is rescheduled). fn reawaken_remotely(mut ~self) { unsafe { - let mtx = &mut self.nasty_deschedule_lock as *mut Mutex; + let mtx = &mut self.nasty_deschedule_lock as *mut StaticNativeMutex; let handle = self.handle.get_mut_ref() as *mut SchedHandle; let _guard = (*mtx).lock(); (*handle).send(RunOnce(self)); diff --git a/src/libnative/bookkeeping.rs b/src/libnative/bookkeeping.rs index e0aaf20e838..b1addc5cda5 100644 --- a/src/libnative/bookkeeping.rs +++ b/src/libnative/bookkeeping.rs @@ -17,10 +17,10 @@ //! The green counterpart for this is bookkeeping on sched pools. use std::sync::atomics; -use std::unstable::mutex::{Mutex, MUTEX_INIT}; +use std::unstable::mutex::{StaticNativeMutex, NATIVE_MUTEX_INIT}; static mut TASK_COUNT: atomics::AtomicUint = atomics::INIT_ATOMIC_UINT; -static mut TASK_LOCK: Mutex = MUTEX_INIT; +static mut TASK_LOCK: StaticNativeMutex = NATIVE_MUTEX_INIT; pub fn increment() { let _ = unsafe { TASK_COUNT.fetch_add(1, atomics::SeqCst) }; diff --git a/src/libnative/io/net.rs b/src/libnative/io/net.rs index 1de729aee2e..b33b54862dc 100644 --- a/src/libnative/io/net.rs +++ b/src/libnative/io/net.rs @@ -218,9 +218,9 @@ pub fn init() { } unsafe { - use std::unstable::mutex::{Mutex, MUTEX_INIT}; + use std::unstable::mutex::{StaticNativeMutex, NATIVE_MUTEX_INIT}; static mut INITIALIZED: bool = false; - static mut LOCK: Mutex = MUTEX_INIT; + static mut LOCK: StaticNativeMutex = NATIVE_MUTEX_INIT; let _guard = LOCK.lock(); if !INITIALIZED { diff --git a/src/libnative/io/timer_helper.rs b/src/libnative/io/timer_helper.rs index 8ddce2c3990..004cd6f3114 100644 --- a/src/libnative/io/timer_helper.rs +++ b/src/libnative/io/timer_helper.rs @@ -22,7 +22,7 @@ use std::cast; use std::rt; -use std::unstable::mutex::{Mutex, MUTEX_INIT}; +use std::unstable::mutex::{StaticNativeMutex, NATIVE_MUTEX_INIT}; use bookkeeping; use io::timer::{Req, Shutdown}; @@ -37,7 +37,7 @@ static mut HELPER_CHAN: *mut Chan = 0 as *mut Chan; static mut HELPER_SIGNAL: imp::signal = 0 as imp::signal; pub fn boot(helper: fn(imp::signal, Port)) { - static mut LOCK: Mutex = MUTEX_INIT; + static mut LOCK: StaticNativeMutex = NATIVE_MUTEX_INIT; static mut INITIALIZED: bool = false; unsafe { diff --git a/src/libnative/task.rs b/src/libnative/task.rs index d940edcadc7..e4a8c45eb0b 100644 --- a/src/libnative/task.rs +++ b/src/libnative/task.rs @@ -22,7 +22,7 @@ use std::rt::task::{Task, BlockedTask, SendMessage}; use std::rt::thread::Thread; use std::rt; use std::task::TaskOpts; -use std::unstable::mutex::Mutex; +use std::unstable::mutex::StaticNativeMutex; use std::unstable::stack; use io; @@ -40,7 +40,7 @@ pub fn new(stack_bounds: (uint, uint)) -> ~Task { fn ops() -> ~Ops { ~Ops { - lock: unsafe { Mutex::new() }, + lock: unsafe { StaticNativeMutex::new() }, awoken: false, io: io::IoFactory::new(), // these *should* get overwritten @@ -109,7 +109,7 @@ pub fn spawn_opts(opts: TaskOpts, f: proc()) { // This structure is the glue between channels and the 1:1 scheduling mode. This // structure is allocated once per task. struct Ops { - lock: Mutex, // native synchronization + lock: StaticNativeMutex, // native synchronization awoken: bool, // used to prevent spurious wakeups io: io::IoFactory, // local I/O factory diff --git a/src/libstd/comm/shared.rs b/src/libstd/comm/shared.rs index fcd00b70dd1..61fc700c3c0 100644 --- a/src/libstd/comm/shared.rs +++ b/src/libstd/comm/shared.rs @@ -28,7 +28,7 @@ use rt::local::Local; use rt::task::{Task, BlockedTask}; use rt::thread::Thread; use sync::atomics; -use unstable::mutex::Mutex; +use unstable::mutex::StaticNativeMutex; use vec::OwnedVector; use mpsc = sync::mpsc_queue; @@ -53,7 +53,7 @@ pub struct Packet { // this lock protects various portions of this implementation during // select() - select_lock: Mutex, + select_lock: StaticNativeMutex, } pub enum Failure { @@ -72,7 +72,7 @@ impl Packet { channels: atomics::AtomicInt::new(2), port_dropped: atomics::AtomicBool::new(false), sender_drain: atomics::AtomicInt::new(0), - select_lock: unsafe { Mutex::new() }, + select_lock: unsafe { StaticNativeMutex::new() }, }; // see comments in inherit_blocker about why we grab this lock unsafe { p.select_lock.lock_noguard() } diff --git a/src/libstd/os.rs b/src/libstd/os.rs index 4a5958c2cfb..719ed62d03d 100644 --- a/src/libstd/os.rs +++ b/src/libstd/os.rs @@ -144,9 +144,9 @@ Accessing environment variables is not generally threadsafe. Serialize access through a global lock. */ fn with_env_lock(f: || -> T) -> T { - use unstable::mutex::{Mutex, MUTEX_INIT}; + use unstable::mutex::{StaticNativeMutex, NATIVE_MUTEX_INIT}; - static mut lock: Mutex = MUTEX_INIT; + static mut lock: StaticNativeMutex = NATIVE_MUTEX_INIT; unsafe { let _guard = lock.lock(); diff --git a/src/libstd/rt/args.rs b/src/libstd/rt/args.rs index c91797c9559..6f73265978b 100644 --- a/src/libstd/rt/args.rs +++ b/src/libstd/rt/args.rs @@ -68,11 +68,11 @@ mod imp { use option::{Option, Some, None}; use ptr::RawPtr; use iter::Iterator; - use unstable::mutex::{Mutex, MUTEX_INIT}; + use unstable::mutex::{StaticNativeMutex, NATIVE_MUTEX_INIT}; use mem; static mut global_args_ptr: uint = 0; - static mut lock: Mutex = MUTEX_INIT; + static mut lock: StaticNativeMutex = NATIVE_MUTEX_INIT; #[cfg(not(test))] pub unsafe fn init(argc: int, argv: **u8) { diff --git a/src/libstd/unstable/dynamic_lib.rs b/src/libstd/unstable/dynamic_lib.rs index 4828c4ee5af..84fa528ebf1 100644 --- a/src/libstd/unstable/dynamic_lib.rs +++ b/src/libstd/unstable/dynamic_lib.rs @@ -152,8 +152,8 @@ pub mod dl { } pub fn check_for_errors_in(f: || -> T) -> Result { - use unstable::mutex::{Mutex, MUTEX_INIT}; - static mut lock: Mutex = MUTEX_INIT; + use unstable::mutex::{StaticNativeMutex, NATIVE_MUTEX_INIT}; + static mut lock: StaticNativeMutex = NATIVE_MUTEX_INIT; unsafe { // dlerror isn't thread safe, so we need to lock around this entire // sequence diff --git a/src/libstd/unstable/mutex.rs b/src/libstd/unstable/mutex.rs index f0e76de789d..d8d051236b3 100644 --- a/src/libstd/unstable/mutex.rs +++ b/src/libstd/unstable/mutex.rs @@ -11,9 +11,9 @@ //! A native mutex and condition variable type //! //! This module contains bindings to the platform's native mutex/condition -//! variable primitives. It provides a single type, `Mutex`, which can be -//! statically initialized via the `MUTEX_INIT` value. This object serves as both a -//! mutex and a condition variable simultaneously. +//! variable primitives. It provides a single type, `StaticNativeMutex`, which can be +//! statically initialized via the `NATIVE_MUTEX_INIT` value. This object serves as +//! both a mutex and a condition variable simultaneously. //! //! The lock is lazily initialized, but it can only be unsafely destroyed. A //! statically initialized lock doesn't necessarily have a time at which it can @@ -27,21 +27,23 @@ //! //! # Example //! -//! use std::unstable::mutex::{Mutex, MUTEX_INIT}; +//! use std::unstable::mutex::{StaticNativeMutex, NATIVE_MUTEX_INIT}; //! //! // Use a statically initialized mutex -//! static mut lock: Mutex = MUTEX_INIT; +//! static mut lock: StaticNativeMutex = NATIVE_MUTEX_INIT; //! //! unsafe { -//! lock.lock(); -//! lock.unlock(); -//! } +//! let _guard = lock.lock(); +//! } // automatically unlocked here //! //! // Use a normally initialized mutex -//! let mut lock = Mutex::new(); //! unsafe { -//! lock.lock(); -//! lock.unlock(); +//! let mut lock = StaticNativeMutex::new(); +//! +//! // sometimes the RAII guard isn't appropriate +//! lock.lock_noguard(); +//! lock.unlock_noguard(); +//! //! lock.destroy(); //! } @@ -50,7 +52,9 @@ use option::{Option, None, Some}; use ops::Drop; -pub struct Mutex { +/// A native mutex suitable for storing in statics (that is, it has +/// the `destroy` method rather than a destructor). +pub struct StaticNativeMutex { priv inner: imp::Mutex, } @@ -62,33 +66,33 @@ pub struct Mutex { /// then. #[must_use] pub struct LockGuard<'a> { - priv lock: &'a mut Mutex + priv lock: &'a mut StaticNativeMutex } -pub static MUTEX_INIT: Mutex = Mutex { +pub static NATIVE_MUTEX_INIT: StaticNativeMutex = StaticNativeMutex { inner: imp::MUTEX_INIT, }; -impl Mutex { - /// Creates a new mutex - pub unsafe fn new() -> Mutex { - Mutex { inner: imp::Mutex::new() } +impl StaticNativeMutex { + /// Creates a new mutex. + /// + /// Note that a mutex created in this way needs to be explicit + /// freed with a call to `destroy` or it will leak. + pub unsafe fn new() -> StaticNativeMutex { + StaticNativeMutex { inner: imp::Mutex::new() } } /// Acquires this lock. This assumes that the current thread does not /// already hold the lock. /// /// # Example - /// ``` - /// use std::unstable::mutex::Mutex; + /// ```rust + /// use std::unstable::mutex::{StaticNativeMutex, NATIVE_MUTEX_INIT}; + /// static mut LOCK: StaticNativeMutex = NATIVE_MUTEX_INIT; /// unsafe { - /// let mut lock = Mutex::new(); - /// - /// { - /// let _guard = lock.lock(); - /// // critical section... - /// } // automatically unlocked in `_guard`'s destructor - /// } + /// let _guard = LOCK.lock(); + /// // critical section... + /// } // automatically unlocked in `_guard`'s destructor /// ``` pub unsafe fn lock<'a>(&'a mut self) -> LockGuard<'a> { self.inner.lock(); @@ -455,12 +459,12 @@ mod test { use prelude::*; use mem::drop; - use super::{Mutex, MUTEX_INIT}; + use super::{StaticNativeMutex, NATIVE_MUTEX_INIT}; use rt::thread::Thread; #[test] fn smoke_lock() { - static mut lock: Mutex = MUTEX_INIT; + static mut lock: StaticNativeMutex = NATIVE_MUTEX_INIT; unsafe { let _guard = lock.lock(); } @@ -468,7 +472,7 @@ mod test { #[test] fn smoke_cond() { - static mut lock: Mutex = MUTEX_INIT; + static mut lock: StaticNativeMutex = NATIVE_MUTEX_INIT; unsafe { let mut guard = lock.lock(); let t = Thread::start(proc() { @@ -484,7 +488,7 @@ mod test { #[test] fn smoke_lock_noguard() { - static mut lock: Mutex = MUTEX_INIT; + static mut lock: StaticNativeMutex = NATIVE_MUTEX_INIT; unsafe { lock.lock_noguard(); lock.unlock_noguard(); @@ -493,7 +497,7 @@ mod test { #[test] fn smoke_cond_noguard() { - static mut lock: Mutex = MUTEX_INIT; + static mut lock: StaticNativeMutex = NATIVE_MUTEX_INIT; unsafe { lock.lock_noguard(); let t = Thread::start(proc() { @@ -511,7 +515,7 @@ mod test { #[test] fn destroy_immediately() { unsafe { - let mut m = Mutex::new(); + let mut m = StaticNativeMutex::new(); m.destroy(); } } diff --git a/src/libstd/unstable/sync.rs b/src/libstd/unstable/sync.rs index 343eacbf429..0a6de50bf23 100644 --- a/src/libstd/unstable/sync.rs +++ b/src/libstd/unstable/sync.rs @@ -13,10 +13,10 @@ use kinds::Send; use ops::Drop; use option::Option; use sync::arc::UnsafeArc; -use unstable::mutex::{Mutex, LockGuard}; +use unstable::mutex::{StaticNativeMutex, LockGuard}; pub struct LittleLock { - priv l: Mutex, + priv l: StaticNativeMutex, } pub struct LittleGuard<'a> { @@ -31,7 +31,7 @@ impl Drop for LittleLock { impl LittleLock { pub fn new() -> LittleLock { - unsafe { LittleLock { l: Mutex::new() } } + unsafe { LittleLock { l: StaticNativeMutex::new() } } } pub unsafe fn lock<'a>(&'a mut self) -> LittleGuard<'a> { diff --git a/src/libsync/sync/mutex.rs b/src/libsync/sync/mutex.rs index f5914b26e85..b37e2f3a45d 100644 --- a/src/libsync/sync/mutex.rs +++ b/src/libsync/sync/mutex.rs @@ -133,7 +133,7 @@ pub struct StaticMutex { /// uint-cast of the native thread waiting for this mutex priv native_blocker: uint, /// an OS mutex used by native threads - priv lock: mutex::Mutex, + priv lock: mutex::StaticNativeMutex, /// A concurrent mpsc queue used by green threads, along with a count used /// to figure out when to dequeue and enqueue. @@ -150,7 +150,7 @@ pub struct Guard<'a> { /// Static initialization of a mutex. This constant can be used to initialize /// other mutex constants. pub static MUTEX_INIT: StaticMutex = StaticMutex { - lock: mutex::MUTEX_INIT, + lock: mutex::NATIVE_MUTEX_INIT, state: atomics::INIT_ATOMIC_UINT, flavor: Unlocked, green_blocker: 0, @@ -441,7 +441,7 @@ impl Mutex { native_blocker: 0, green_cnt: atomics::AtomicUint::new(0), q: q::Queue::new(), - lock: unsafe { mutex::Mutex::new() }, + lock: unsafe { mutex::StaticNativeMutex::new() }, } } } -- cgit 1.4.1-3-g733a5 From 0f4294b4e2887ffe9d0532564521c456bb89a780 Mon Sep 17 00:00:00 2001 From: Huon Wilson Date: Sat, 15 Feb 2014 12:53:23 +1100 Subject: sync: Add `#[must_use]` to the Mutex guard. This helps people remember to save the return value to keep the mutex locked as appropriate. --- src/libsync/sync/mutex.rs | 1 + 1 file changed, 1 insertion(+) (limited to 'src/libsync') diff --git a/src/libsync/sync/mutex.rs b/src/libsync/sync/mutex.rs index b37e2f3a45d..2bd85526e68 100644 --- a/src/libsync/sync/mutex.rs +++ b/src/libsync/sync/mutex.rs @@ -143,6 +143,7 @@ pub struct StaticMutex { /// An RAII implementation of a "scoped lock" of a mutex. When this structure is /// dropped (falls out of scope), the lock will be unlocked. +#[must_use] pub struct Guard<'a> { priv lock: &'a mut StaticMutex, } -- cgit 1.4.1-3-g733a5