Skip to content

Commit 5b02cc5

Browse files
committed
---
yaml --- r: 142603 b: refs/heads/try2 c: d4de99a h: refs/heads/master i: 142601: 82143d1 142599: 087a9dd v: v3
1 parent 5eac188 commit 5b02cc5

File tree

2 files changed

+16
-12
lines changed

2 files changed

+16
-12
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ refs/heads/snap-stage3: 78a7676898d9f80ab540c6df5d4c9ce35bb50463
55
refs/heads/try: 519addf6277dbafccbb4159db4b710c37eaa2ec5
66
refs/tags/release-0.1: 1f5c5126e96c79d22cb7862f75304136e204f105
77
refs/heads/ndm: f3868061cd7988080c30d6d5bf352a5a5fe2460b
8-
refs/heads/try2: d6ccc6bc99386ae20ac03b68e7ec504a16068242
8+
refs/heads/try2: d4de99aa6c53b0eb0d5be2ccfc62e2c89b2cd2df
99
refs/heads/dist-snap: ba4081a5a8573875fed17545846f6f6902c8ba8d
1010
refs/tags/release-0.2: c870d2dffb391e14efb05aa27898f1f6333a9596
1111
refs/tags/release-0.3: b5f0d0f648d9a6153664837026ba1be43d3e2503

branches/try2/src/libstd/rt/uv/uvio.rs

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ use rt::sched::Scheduler;
2424
use rt::io::{standard_error, OtherIoError};
2525
use rt::tube::Tube;
2626
use rt::local::Local;
27-
use unstable::sync::{UnsafeAtomicRcBox, AtomicInt};
27+
use unstable::sync::{Exclusive, exclusive};
2828

2929
#[cfg(test)] use container::Container;
3030
#[cfg(test)] use uint;
@@ -105,21 +105,20 @@ fn test_callback_run_once() {
105105
pub struct UvRemoteCallback {
106106
// The uv async handle for triggering the callback
107107
async: AsyncWatcher,
108-
// An atomic flag to tell the callback to exit,
109-
// set from the dtor.
110-
exit_flag: UnsafeAtomicRcBox<AtomicInt>
108+
// A flag to tell the callback to exit, set from the dtor. This is
109+
// almost never contested - only in rare races with the dtor.
110+
exit_flag: Exclusive<bool>
111111
}
112112

113113
impl UvRemoteCallback {
114114
pub fn new(loop_: &mut Loop, f: ~fn()) -> UvRemoteCallback {
115-
let exit_flag = UnsafeAtomicRcBox::new(AtomicInt::new(0));
115+
let exit_flag = exclusive(false);
116116
let exit_flag_clone = exit_flag.clone();
117117
let async = do AsyncWatcher::new(loop_) |watcher, status| {
118118
assert!(status.is_none());
119119
f();
120-
let exit_flag_ptr = exit_flag_clone.get();
121-
unsafe {
122-
if (*exit_flag_ptr).load() == 1 {
120+
do exit_flag_clone.with_imm |&should_exit| {
121+
if should_exit {
123122
watcher.close(||());
124123
}
125124
}
@@ -139,9 +138,14 @@ impl Drop for UvRemoteCallback {
139138
fn finalize(&self) {
140139
unsafe {
141140
let this: &mut UvRemoteCallback = cast::transmute_mut(self);
142-
let exit_flag_ptr = this.exit_flag.get();
143-
(*exit_flag_ptr).store(1);
144-
this.async.send();
141+
do this.exit_flag.with |should_exit| {
142+
// NB: These two things need to happen atomically. Otherwise
143+
// the event handler could wake up due to a *previous*
144+
// signal and see the exit flag, destroying the handle
145+
// before the final send.
146+
*should_exit = true;
147+
this.async.send();
148+
}
145149
}
146150
}
147151
}

0 commit comments

Comments
 (0)