Skip to content

Commit 0937f65

Browse files
committed
std: add a NativeMutex type as a wrapper to destroy StaticNativeMutex.
This obsoletes LittleLock, and so it is removed.
1 parent b87ed60 commit 0937f65

File tree

4 files changed

+115
-73
lines changed

4 files changed

+115
-73
lines changed

src/libgreen/simple.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,10 @@ use std::rt::local::Local;
1717
use std::rt::rtio;
1818
use std::rt::task::{Task, BlockedTask};
1919
use std::task::TaskOpts;
20-
use std::unstable::sync::LittleLock;
20+
use std::unstable::mutex::NativeMutex;
2121

2222
struct SimpleTask {
23-
lock: LittleLock,
23+
lock: NativeMutex,
2424
awoken: bool,
2525
}
2626

@@ -59,9 +59,9 @@ impl Runtime for SimpleTask {
5959
to_wake.put_runtime(self as ~Runtime);
6060
unsafe {
6161
cast::forget(to_wake);
62-
let _l = (*me).lock.lock();
62+
let mut guard = (*me).lock.lock();
6363
(*me).awoken = true;
64-
(*me).lock.signal();
64+
guard.signal();
6565
}
6666
}
6767

@@ -83,7 +83,7 @@ impl Runtime for SimpleTask {
8383
pub fn task() -> ~Task {
8484
let mut task = ~Task::new();
8585
task.put_runtime(~SimpleTask {
86-
lock: LittleLock::new(),
86+
lock: unsafe {NativeMutex::new()},
8787
awoken: false,
8888
} as ~Runtime);
8989
return task;

src/librustuv/queue.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
use std::cast;
2424
use std::libc::{c_void, c_int};
2525
use std::rt::task::BlockedTask;
26-
use std::unstable::sync::LittleLock;
26+
use std::unstable::mutex::NativeMutex;
2727
use std::sync::arc::UnsafeArc;
2828
use mpsc = std::sync::mpsc_queue;
2929

@@ -39,7 +39,7 @@ enum Message {
3939

4040
struct State {
4141
handle: *uvll::uv_async_t,
42-
lock: LittleLock, // see comments in async_cb for why this is needed
42+
lock: NativeMutex, // see comments in async_cb for why this is needed
4343
queue: mpsc::Queue<Message>,
4444
}
4545

@@ -112,7 +112,7 @@ impl QueuePool {
112112
let handle = UvHandle::alloc(None::<AsyncWatcher>, uvll::UV_ASYNC);
113113
let state = UnsafeArc::new(State {
114114
handle: handle,
115-
lock: LittleLock::new(),
115+
lock: unsafe {NativeMutex::new()},
116116
queue: mpsc::Queue::new(),
117117
});
118118
let q = ~QueuePool {

src/libstd/unstable/mutex.rs

Lines changed: 100 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -8,44 +8,50 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
//! A native mutex and condition variable type
11+
//! A native mutex and condition variable type.
1212
//!
1313
//! This module contains bindings to the platform's native mutex/condition
14-
//! variable primitives. It provides a single type, `StaticNativeMutex`, which can be
15-
//! statically initialized via the `NATIVE_MUTEX_INIT` value. This object serves as
16-
//! both a mutex and a condition variable simultaneously.
14+
//! variable primitives. It provides two types: `StaticNativeMutex`, which can
15+
//! be statically initialized via the `NATIVE_MUTEX_INIT` value, and a simple
16+
//! wrapper `NativeMutex` that has a destructor to clean up after itself. These
17+
//! objects serve as both mutexes and condition variables simultaneously.
1718
//!
18-
//! The lock is lazily initialized, but it can only be unsafely destroyed. A
19-
//! statically initialized lock doesn't necessarily have a time at which it can
20-
//! get deallocated. For this reason, there is no `Drop` implementation of the
21-
//! mutex, but rather the `destroy()` method must be invoked manually if
22-
//! destruction of the mutex is desired.
19+
//! The static lock is lazily initialized, but it can only be unsafely
20+
//! destroyed. A statically initialized lock doesn't necessarily have a time at
21+
//! which it can get deallocated. For this reason, there is no `Drop`
22+
//! implementation of the static mutex, but rather the `destroy()` method must
23+
//! be invoked manually if destruction of the mutex is desired.
2324
//!
24-
//! It is not recommended to use this type for idiomatic rust use. This type is
25-
//! appropriate where no other options are available, but other rust concurrency
26-
//! primitives should be used before this type.
25+
//! The non-static `NativeMutex` type does have a destructor, but cannot be
26+
//! statically initialized.
27+
//!
28+
//! It is not recommended to use this type for idiomatic rust use. These types
29+
//! are appropriate where no other options are available, but other rust
30+
//! concurrency primitives should be used before them.
2731
//!
2832
//! # Example
2933
//!
3034
//! use std::unstable::mutex::{StaticNativeMutex, NATIVE_MUTEX_INIT};
3135
//!
3236
//! // Use a statically initialized mutex
33-
//! static mut lock: StaticNativeMutex = NATIVE_MUTEX_INIT;
37+
//! static mut LOCK: StaticNativeMutex = NATIVE_MUTEX_INIT;
3438
//!
3539
//! unsafe {
36-
//! let _guard = lock.lock();
40+
//! let _guard = LOCK.lock();
3741
//! } // automatically unlocked here
3842
//!
3943
//! // Use a normally initialized mutex
4044
//! unsafe {
41-
//! let mut lock = StaticNativeMutex::new();
45+
//! let mut lock = NativeMutex::new();
46+
//!
47+
//! {
48+
//! let _guard = lock.lock();
49+
//! } // unlocked here
4250
//!
4351
//! // sometimes the RAII guard isn't appropriate
4452
//! lock.lock_noguard();
4553
//! lock.unlock_noguard();
46-
//!
47-
//! lock.destroy();
48-
//! }
54+
//! } // `lock` is deallocated here
4955
5056
#[allow(non_camel_case_types)];
5157

@@ -54,10 +60,20 @@ use ops::Drop;
5460

5561
/// A native mutex suitable for storing in statics (that is, it has
5662
/// the `destroy` method rather than a destructor).
63+
///
64+
/// Prefer the `NativeMutex` type where possible.
5765
pub struct StaticNativeMutex {
5866
priv inner: imp::Mutex,
5967
}
6068

69+
/// A native mutex with a destructor for clean-up.
70+
///
71+
/// See `StaticNativeMutex` for a version that is suitable for storing in
72+
/// statics.
73+
pub struct NativeMutex {
74+
priv inner: StaticNativeMutex
75+
}
76+
6177
/// Automatically unlocks the mutex that it was created from on
6278
/// destruction.
6379
///
@@ -144,6 +160,72 @@ impl StaticNativeMutex {
144160
pub unsafe fn destroy(&mut self) { self.inner.destroy() }
145161
}
146162

163+
impl NativeMutex {
164+
/// Creates a new mutex.
165+
///
166+
/// The user must be careful to ensure the mutex is not locked when its is
167+
/// being destroyed.
168+
pub unsafe fn new() -> NativeMutex {
169+
NativeMutex { inner: StaticNativeMutex::new() }
170+
}
171+
172+
/// Acquires this lock. This assumes that the current thread does not
173+
/// already hold the lock.
174+
///
175+
/// # Example
176+
/// ```rust
177+
/// use std::unstable::mutex::NativeMutex;
178+
/// let mut lock = NativeMutex::new();
179+
/// unsafe {
180+
/// let _guard = lock.lock();
181+
/// // critical section...
182+
/// } // automatically unlocked in `_guard`'s destructor
183+
/// ```
184+
pub unsafe fn lock<'a>(&'a mut self) -> LockGuard<'a> {
185+
self.inner.lock()
186+
}
187+
188+
/// Attempts to acquire the lock. The value returned is `Some` if
189+
/// the attempt succeeded.
190+
pub unsafe fn trylock<'a>(&'a mut self) -> Option<LockGuard<'a>> {
191+
self.inner.trylock()
192+
}
193+
194+
/// Acquire the lock without creating a `LockGuard`.
195+
///
196+
/// Prefer using `.lock`.
197+
pub unsafe fn lock_noguard(&mut self) { self.inner.lock_noguard() }
198+
199+
/// Attempts to acquire the lock without creating a
200+
/// `LockGuard`. The value returned is whether the lock was
201+
/// acquired or not.
202+
///
203+
/// Prefer using `.trylock`.
204+
pub unsafe fn trylock_noguard(&mut self) -> bool {
205+
self.inner.trylock_noguard()
206+
}
207+
208+
/// Unlocks the lock. This assumes that the current thread already holds the
209+
/// lock.
210+
pub unsafe fn unlock_noguard(&mut self) { self.inner.unlock_noguard() }
211+
212+
/// Block on the internal condition variable.
213+
///
214+
/// This function assumes that the lock is already held. Prefer
215+
/// using `LockGuard.wait` since that guarantees that the lock is
216+
/// held.
217+
pub unsafe fn wait_noguard(&mut self) { self.inner.wait_noguard() }
218+
219+
/// Signals a thread in `wait` to wake up
220+
pub unsafe fn signal_noguard(&mut self) { self.inner.signal_noguard() }
221+
}
222+
223+
impl Drop for NativeMutex {
224+
fn drop(&mut self) {
225+
unsafe {self.inner.destroy()}
226+
}
227+
}
228+
147229
impl<'a> LockGuard<'a> {
148230
/// Block on the internal condition variable.
149231
pub unsafe fn wait(&mut self) {

src/libstd/unstable/sync.rs

Lines changed: 7 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -10,51 +10,11 @@
1010

1111
use clone::Clone;
1212
use kinds::Send;
13-
use ops::Drop;
14-
use option::Option;
1513
use sync::arc::UnsafeArc;
16-
use unstable::mutex::{StaticNativeMutex, LockGuard};
17-
18-
pub struct LittleLock {
19-
priv l: StaticNativeMutex,
20-
}
21-
22-
pub struct LittleGuard<'a> {
23-
priv l: LockGuard<'a>
24-
}
25-
26-
impl Drop for LittleLock {
27-
fn drop(&mut self) {
28-
unsafe { self.l.destroy(); }
29-
}
30-
}
31-
32-
impl LittleLock {
33-
pub fn new() -> LittleLock {
34-
unsafe { LittleLock { l: StaticNativeMutex::new() } }
35-
}
36-
37-
pub unsafe fn lock<'a>(&'a mut self) -> LittleGuard<'a> {
38-
LittleGuard { l: self.l.lock() }
39-
}
40-
41-
pub unsafe fn try_lock<'a>(&'a mut self) -> Option<LittleGuard<'a>> {
42-
self.l.trylock().map(|guard| LittleGuard { l: guard })
43-
}
44-
45-
pub unsafe fn signal(&mut self) {
46-
self.l.signal_noguard();
47-
}
48-
}
49-
50-
impl<'a> LittleGuard<'a> {
51-
pub unsafe fn wait(&mut self) {
52-
self.l.wait();
53-
}
54-
}
14+
use unstable::mutex::NativeMutex;
5515

5616
struct ExData<T> {
57-
lock: LittleLock,
17+
lock: NativeMutex,
5818
failed: bool,
5919
data: T,
6020
}
@@ -83,7 +43,7 @@ impl<T:Send> Clone for Exclusive<T> {
8343
impl<T:Send> Exclusive<T> {
8444
pub fn new(user_data: T) -> Exclusive<T> {
8545
let data = ExData {
86-
lock: LittleLock::new(),
46+
lock: unsafe {NativeMutex::new()},
8747
failed: false,
8848
data: user_data
8949
};
@@ -92,8 +52,8 @@ impl<T:Send> Exclusive<T> {
9252
}
9353
}
9454

95-
// Exactly like std::arc::MutexArc,access(), but with the LittleLock
96-
// instead of a proper mutex. Same reason for being unsafe.
55+
// Exactly like sync::MutexArc.access(). Same reason for being
56+
// unsafe.
9757
//
9858
// Currently, scheduling operations (i.e., descheduling, receiving on a pipe,
9959
// accessing the provided condition variable) are prohibited while inside
@@ -119,14 +79,14 @@ impl<T:Send> Exclusive<T> {
11979
#[inline]
12080
pub unsafe fn hold_and_signal(&self, f: |x: &mut T|) {
12181
let rec = self.x.get();
122-
let _l = (*rec).lock.lock();
82+
let mut guard = (*rec).lock.lock();
12383
if (*rec).failed {
12484
fail!("Poisoned Exclusive::new - another task failed inside!");
12585
}
12686
(*rec).failed = true;
12787
f(&mut (*rec).data);
12888
(*rec).failed = false;
129-
(*rec).lock.signal();
89+
guard.signal();
13090
}
13191

13292
#[inline]

0 commit comments

Comments
 (0)