@@ -26,6 +26,7 @@ use rt::local::Local;
2626use rt:: rtio:: * ;
2727use rt:: sched:: { Scheduler , SchedHandle } ;
2828use rt:: tube:: Tube ;
29+ use rt:: task:: SchedHome ;
2930use rt:: uv:: * ;
3031use rt:: uv:: idle:: IdleWatcher ;
3132use rt:: uv:: net:: { UvIpv4SocketAddr , UvIpv6SocketAddr } ;
@@ -47,76 +48,80 @@ use task;
4748// XXX we should not be calling uvll functions in here.
4849
4950trait 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