Rework the idle callback to have a safer interface

It turns out that the uv implementation would cause use-after-free if the idle
callback was used after the call to `close`, and additionally nothing would ever
really work that well if `start()` were called twice. To change this, the
`start` and `close` methods were removed in favor of specifying the callback at
creation, and allowing destruction to take care of closing the watcher.
This commit is contained in:
Alex Crichton
2013-11-06 11:38:53 -08:00
parent d08aadcc9a
commit b545751597
5 changed files with 80 additions and 87 deletions

View File

@@ -107,7 +107,7 @@ impl BasicLoop {
match self.idle {
Some(idle) => {
if (*idle).active {
(*idle).work.get_mut_ref().call();
(*idle).work.call();
}
}
None => {}
@@ -150,8 +150,8 @@ impl EventLoop for BasicLoop {
}
// XXX: Seems like a really weird requirement to have an event loop provide.
fn pausible_idle_callback(&mut self) -> ~PausibleIdleCallback {
let callback = ~BasicPausible::new(self);
fn pausible_idle_callback(&mut self, cb: ~Callback) -> ~PausibleIdleCallback {
let callback = ~BasicPausible::new(self, cb);
rtassert!(self.idle.is_none());
unsafe {
let cb_ptr: &*mut BasicPausible = cast::transmute(&callback);
@@ -204,36 +204,27 @@ impl Drop for BasicRemote {
struct BasicPausible {
eloop: *mut BasicLoop,
work: Option<~Callback>,
work: ~Callback,
active: bool,
}
impl BasicPausible {
fn new(eloop: &mut BasicLoop) -> BasicPausible {
fn new(eloop: &mut BasicLoop, cb: ~Callback) -> BasicPausible {
BasicPausible {
active: false,
work: None,
work: cb,
eloop: eloop,
}
}
}
impl PausibleIdleCallback for BasicPausible {
fn start(&mut self, f: ~Callback) {
rtassert!(!self.active && self.work.is_none());
self.active = true;
self.work = Some(f);
}
fn pause(&mut self) {
self.active = false;
}
fn resume(&mut self) {
self.active = true;
}
fn close(&mut self) {
self.active = false;
self.work = None;
}
}
impl Drop for BasicPausible {