Skip to content

Commit efb8924

Browse files
committed
Add a variant of home_for_io that consumes the handle. Refactor out common parts of the home_for_io variants.
1 parent ed422b8 commit efb8924

File tree

1 file changed

+53
-48
lines changed

1 file changed

+53
-48
lines changed

src/libstd/rt/uv/uvio.rs

Lines changed: 53 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ use rt::local::Local;
2626
use rt::rtio::*;
2727
use rt::sched::{Scheduler, SchedHandle};
2828
use rt::tube::Tube;
29+
use rt::task::SchedHome;
2930
use rt::uv::*;
3031
use rt::uv::idle::IdleWatcher;
3132
use rt::uv::net::{UvIpv4SocketAddr, UvIpv6SocketAddr};
@@ -47,76 +48,80 @@ use task;
4748
// XXX we should not be calling uvll functions in here.
4849

4950
trait HomingIO {
51+
5052
fn home<'r>(&'r mut self) -> &'r mut SchedHandle;
53+
5154
/* XXX This will move pinned tasks to do IO on the proper scheduler
5255
* and then move them back to their home.
5356
*/
54-
fn home_for_io<A>(&mut self, io: &fn(&mut Self) -> A) -> A {
55-
use rt::sched::{PinnedTask, TaskFromFriend};
56-
// go home
57-
let old_home = Cell::new_empty();
58-
let old_home_ptr = &old_home;
57+
fn go_to_IO_home(&mut self) -> SchedHome {
58+
use rt::sched::PinnedTask;
59+
5960
do task::unkillable { // FIXME(#8674)
60-
let scheduler: ~Scheduler = Local::take();
61-
do scheduler.deschedule_running_task_and_then |_, task| {
62-
// get the old home first
63-
do task.wake().map_move |mut task| {
64-
old_home_ptr.put_back(task.take_unwrap_home());
65-
self.home().send(PinnedTask(task));
66-
};
61+
let mut old = None;
62+
{
63+
let ptr = &mut old;
64+
let scheduler: ~Scheduler = Local::take();
65+
do scheduler.deschedule_running_task_and_then |_, task| {
66+
/* FIXME(#8674) if the task was already killed then wake
67+
* will return None. In that case, the home pointer will never be set.
68+
*
69+
* RESOLUTION IDEA: Since the task is dead, we should just abort the IO action.
70+
*/
71+
do task.wake().map_move |mut task| {
72+
*ptr = Some(task.take_unwrap_home());
73+
self.home().send(PinnedTask(task));
74+
};
75+
}
6776
}
77+
old.expect("No old home because task had already been killed.")
6878
}
79+
}
6980

70-
// do IO
71-
let a = io(self);
81+
// XXX dummy self param
82+
fn restore_original_home(_dummy_self: Option<Self>, old: SchedHome) {
83+
use rt::sched::TaskFromFriend;
7284

73-
// unhome home
85+
let old = Cell::new(old);
7486
do task::unkillable { // FIXME(#8674)
7587
let scheduler: ~Scheduler = Local::take();
7688
do scheduler.deschedule_running_task_and_then |scheduler, task| {
89+
/* FIXME(#8674) if the task was already killed then wake
90+
* will return None. In that case, the home pointer will never be restored.
91+
*
92+
* RESOLUTION IDEA: Since the task is dead, we should just abort the IO action.
93+
*/
7794
do task.wake().map_move |mut task| {
78-
task.give_home(old_home.take());
95+
task.give_home(old.take());
7996
scheduler.make_handle().send(TaskFromFriend(task));
8097
};
8198
}
8299
}
83-
84-
// return the result of the IO
85-
a
86100
}
87101

88-
fn home_for_io_with_sched<A>(&mut self, io_sched: &fn(&mut Self, ~Scheduler) -> A) -> A {
89-
use rt::sched::{PinnedTask, TaskFromFriend};
90-
91-
do task::unkillable { // FIXME(#8674)
92-
// go home
93-
let old_home = Cell::new_empty();
94-
let old_home_ptr = &old_home;
95-
let scheduler: ~Scheduler = Local::take();
96-
do scheduler.deschedule_running_task_and_then |_, task| {
97-
// get the old home first
98-
do task.wake().map_move |mut task| {
99-
old_home_ptr.put_back(task.take_unwrap_home());
100-
self.home().send(PinnedTask(task));
101-
};
102-
}
102+
fn home_for_io<A>(&mut self, io: &fn(&mut Self) -> A) -> A {
103+
let home = self.go_to_IO_home();
104+
let a = io(self); // do IO
105+
HomingIO::restore_original_home(None::<Self> /* XXX dummy self */, home);
106+
a // return the result of the IO
107+
}
103108

104-
// do IO
105-
let scheduler: ~Scheduler = Local::take();
106-
let a = io_sched(self, scheduler);
109+
fn home_for_io_consume<A>(self, io: &fn(Self) -> A) -> A {
110+
let mut this = self;
111+
let home = this.go_to_IO_home();
112+
let a = io(this); // do IO
113+
HomingIO::restore_original_home(None::<Self> /* XXX dummy self */, home);
114+
a // return the result of the IO
115+
}
107116

108-
// unhome home
117+
fn home_for_io_with_sched<A>(&mut self, io_sched: &fn(&mut Self, ~Scheduler) -> A) -> A {
118+
let home = self.go_to_IO_home();
119+
let a = do task::unkillable { // FIXME(#8674)
109120
let scheduler: ~Scheduler = Local::take();
110-
do scheduler.deschedule_running_task_and_then |scheduler, task| {
111-
do task.wake().map_move |mut task| {
112-
task.give_home(old_home.take());
113-
scheduler.make_handle().send(TaskFromFriend(task));
114-
};
115-
}
116-
117-
// return the result of the IO
118-
a
119-
}
121+
io_sched(self, scheduler) // do IO and scheduling action
122+
};
123+
HomingIO::restore_original_home(None::<Self> /* XXX dummy self */, home);
124+
a // return result of IO
120125
}
121126
}
122127

0 commit comments

Comments
 (0)