Skip to content

Commit 76a59fd

Browse files
committed
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.
1 parent fba32ea commit 76a59fd

File tree

13 files changed

+134
-94
lines changed

13 files changed

+134
-94
lines changed

src/libgreen/sched.rs

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -669,8 +669,7 @@ impl Scheduler {
669669
// is acquired here. This is the resumption points and the "bounce"
670670
// that it is referring to.
671671
unsafe {
672-
current_task.nasty_deschedule_lock.lock();
673-
current_task.nasty_deschedule_lock.unlock();
672+
let _guard = current_task.nasty_deschedule_lock.lock();
674673
}
675674
return current_task;
676675
}
@@ -766,9 +765,10 @@ impl Scheduler {
766765
// unlocked the lock so there's no worry of this memory going away.
767766
let cur = self.change_task_context(cur, next, |sched, mut task| {
768767
let lock: *mut Mutex = &mut task.nasty_deschedule_lock;
769-
unsafe { (*lock).lock() }
770-
f(sched, BlockedTask::block(task.swap()));
771-
unsafe { (*lock).unlock() }
768+
unsafe {
769+
let _guard = (*lock).lock();
770+
f(sched, BlockedTask::block(task.swap()));
771+
}
772772
});
773773
cur.put();
774774
}
@@ -1466,12 +1466,11 @@ mod test {
14661466
let mut handle = pool.spawn_sched();
14671467
handle.send(PinnedTask(pool.task(TaskOpts::new(), proc() {
14681468
unsafe {
1469-
LOCK.lock();
1469+
let mut guard = LOCK.lock();
14701470

14711471
start_ch.send(());
1472-
LOCK.wait(); // block the scheduler thread
1473-
LOCK.signal(); // let them know we have the lock
1474-
LOCK.unlock();
1472+
guard.wait(); // block the scheduler thread
1473+
guard.signal(); // let them know we have the lock
14751474
}
14761475

14771476
fin_ch.send(());
@@ -1503,10 +1502,9 @@ mod test {
15031502
child_ch.send(20);
15041503
pingpong(&parent_po, &child_ch);
15051504
unsafe {
1506-
LOCK.lock();
1507-
LOCK.signal(); // wakeup waiting scheduler
1508-
LOCK.wait(); // wait for them to grab the lock
1509-
LOCK.unlock();
1505+
let mut guard = LOCK.lock();
1506+
guard.signal(); // wakeup waiting scheduler
1507+
guard.wait(); // wait for them to grab the lock
15101508
}
15111509
})));
15121510
drop(handle);

src/libgreen/task.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -324,9 +324,8 @@ impl GreenTask {
324324
unsafe {
325325
let mtx = &mut self.nasty_deschedule_lock as *mut Mutex;
326326
let handle = self.handle.get_mut_ref() as *mut SchedHandle;
327-
(*mtx).lock();
327+
let _guard = (*mtx).lock();
328328
(*handle).send(RunOnce(self));
329-
(*mtx).unlock();
330329
}
331330
}
332331
}

src/libnative/bookkeeping.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,8 @@ pub fn increment() {
2929
pub fn decrement() {
3030
unsafe {
3131
if TASK_COUNT.fetch_sub(1, atomics::SeqCst) == 1 {
32-
TASK_LOCK.lock();
33-
TASK_LOCK.signal();
34-
TASK_LOCK.unlock();
32+
let mut guard = TASK_LOCK.lock();
33+
guard.signal();
3534
}
3635
}
3736
}
@@ -40,11 +39,12 @@ pub fn decrement() {
4039
/// the entry points of native programs
4140
pub fn wait_for_other_tasks() {
4241
unsafe {
43-
TASK_LOCK.lock();
44-
while TASK_COUNT.load(atomics::SeqCst) > 0 {
45-
TASK_LOCK.wait();
42+
{
43+
let mut guard = TASK_LOCK.lock();
44+
while TASK_COUNT.load(atomics::SeqCst) > 0 {
45+
guard.wait();
46+
}
4647
}
47-
TASK_LOCK.unlock();
4848
TASK_LOCK.destroy();
4949
}
5050
}

src/libnative/io/net.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -222,15 +222,14 @@ pub fn init() {
222222
static mut INITIALIZED: bool = false;
223223
static mut LOCK: Mutex = MUTEX_INIT;
224224

225-
LOCK.lock();
225+
let _guard = LOCK.lock();
226226
if !INITIALIZED {
227227
let mut data: WSADATA = mem::init();
228228
let ret = WSAStartup(0x202, // version 2.2
229229
&mut data);
230230
assert_eq!(ret, 0);
231231
INITIALIZED = true;
232232
}
233-
LOCK.unlock();
234233
}
235234
}
236235

src/libnative/io/timer_helper.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ pub fn boot(helper: fn(imp::signal, Port<Req>)) {
4141
static mut INITIALIZED: bool = false;
4242

4343
unsafe {
44-
LOCK.lock();
44+
let mut _guard = LOCK.lock();
4545
if !INITIALIZED {
4646
let (msgp, msgc) = Chan::new();
4747
// promote this to a shared channel
@@ -58,7 +58,6 @@ pub fn boot(helper: fn(imp::signal, Port<Req>)) {
5858
rt::at_exit(proc() { shutdown() });
5959
INITIALIZED = true;
6060
}
61-
LOCK.unlock();
6261
}
6362
}
6463

src/libnative/task.rs

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -191,20 +191,19 @@ impl rt::Runtime for Ops {
191191
let task = BlockedTask::block(cur_task);
192192

193193
if times == 1 {
194-
(*me).lock.lock();
194+
let mut guard = (*me).lock.lock();
195195
(*me).awoken = false;
196196
match f(task) {
197197
Ok(()) => {
198198
while !(*me).awoken {
199-
(*me).lock.wait();
199+
guard.wait();
200200
}
201201
}
202202
Err(task) => { cast::forget(task.wake()); }
203203
}
204-
(*me).lock.unlock();
205204
} else {
206205
let mut iter = task.make_selectable(times);
207-
(*me).lock.lock();
206+
let mut guard = (*me).lock.lock();
208207
(*me).awoken = false;
209208
let success = iter.all(|task| {
210209
match f(task) {
@@ -216,9 +215,8 @@ impl rt::Runtime for Ops {
216215
}
217216
});
218217
while success && !(*me).awoken {
219-
(*me).lock.wait();
218+
guard.wait();
220219
}
221-
(*me).lock.unlock();
222220
}
223221
// re-acquire ownership of the task
224222
cur_task = cast::transmute::<uint, ~Task>(cur_task_dupe);
@@ -235,10 +233,9 @@ impl rt::Runtime for Ops {
235233
let me = &mut *self as *mut Ops;
236234
to_wake.put_runtime(self as ~rt::Runtime);
237235
cast::forget(to_wake);
238-
(*me).lock.lock();
236+
let mut guard = (*me).lock.lock();
239237
(*me).awoken = true;
240-
(*me).lock.signal();
241-
(*me).lock.unlock();
238+
guard.signal();
242239
}
243240
}
244241

src/libstd/comm/shared.rs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ impl<T: Send> Packet<T> {
7575
select_lock: unsafe { Mutex::new() },
7676
};
7777
// see comments in inherit_blocker about why we grab this lock
78-
unsafe { p.select_lock.lock() }
78+
unsafe { p.select_lock.lock_noguard() }
7979
return p;
8080
}
8181

@@ -124,7 +124,7 @@ impl<T: Send> Packet<T> {
124124
// interfere with this method. After we unlock this lock, we're
125125
// signifying that we're done modifying self.cnt and self.to_wake and
126126
// the port is ready for the world to continue using it.
127-
unsafe { self.select_lock.unlock() }
127+
unsafe { self.select_lock.unlock_noguard() }
128128
}
129129

130130
pub fn send(&mut self, t: T) -> bool {
@@ -438,8 +438,7 @@ impl<T: Send> Packet<T> {
438438
// about looking at and dealing with to_wake. Once we have acquired the
439439
// lock, we are guaranteed that inherit_blocker is done.
440440
unsafe {
441-
self.select_lock.lock();
442-
self.select_lock.unlock();
441+
let _guard = self.select_lock.lock();
443442
}
444443

445444
// Like the stream implementation, we want to make sure that the count

src/libstd/os.rs

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,6 @@ use ptr;
4444
use str;
4545
use str::{Str, StrSlice};
4646
use fmt;
47-
use unstable::finally::Finally;
4847
use sync::atomics::{AtomicInt, INIT_ATOMIC_INT, SeqCst};
4948
use path::{Path, GenericPath};
5049
use iter::Iterator;
@@ -146,15 +145,12 @@ Serialize access through a global lock.
146145
*/
147146
fn with_env_lock<T>(f: || -> T) -> T {
148147
use unstable::mutex::{Mutex, MUTEX_INIT};
149-
use unstable::finally::Finally;
150148

151149
static mut lock: Mutex = MUTEX_INIT;
152150

153151
unsafe {
154-
return (|| {
155-
lock.lock();
156-
f()
157-
}).finally(|| lock.unlock());
152+
let _guard = lock.lock();
153+
f()
158154
}
159155
}
160156

src/libstd/rt/args.rs

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,6 @@ mod imp {
6868
use option::{Option, Some, None};
6969
use ptr::RawPtr;
7070
use iter::Iterator;
71-
use unstable::finally::Finally;
7271
use unstable::mutex::{Mutex, MUTEX_INIT};
7372
use mem;
7473

@@ -111,16 +110,10 @@ mod imp {
111110
}
112111

113112
fn with_lock<T>(f: || -> T) -> T {
114-
(|| {
115-
unsafe {
116-
lock.lock();
117-
f()
118-
}
119-
}).finally(|| {
120-
unsafe {
121-
lock.unlock();
122-
}
123-
})
113+
unsafe {
114+
let _guard = lock.lock();
115+
f()
116+
}
124117
}
125118

126119
fn get_global_ptr() -> *mut Option<~~[~[u8]]> {

src/libstd/unstable/dynamic_lib.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ pub mod dl {
157157
unsafe {
158158
// dlerror isn't thread safe, so we need to lock around this entire
159159
// sequence
160-
lock.lock();
160+
let _guard = lock.lock();
161161
let _old_error = dlerror();
162162

163163
let result = f();
@@ -168,7 +168,7 @@ pub mod dl {
168168
} else {
169169
Err(str::raw::from_c_str(last_error))
170170
};
171-
lock.unlock();
171+
172172
ret
173173
}
174174
}

0 commit comments

Comments
 (0)