@@ -26,6 +26,7 @@ use rt::local::Local;
26
26
use rt:: rtio:: * ;
27
27
use rt:: sched:: { Scheduler , SchedHandle } ;
28
28
use rt:: tube:: Tube ;
29
+ use rt:: task:: SchedHome ;
29
30
use rt:: uv:: * ;
30
31
use rt:: uv:: idle:: IdleWatcher ;
31
32
use rt:: uv:: net:: { UvIpv4SocketAddr , UvIpv6SocketAddr } ;
@@ -47,76 +48,80 @@ use task;
47
48
// XXX we should not be calling uvll functions in here.
48
49
49
50
trait HomingIO {
51
+
50
52
fn home < ' r > ( & ' r mut self ) -> & ' r mut SchedHandle ;
53
+
51
54
/* XXX This will move pinned tasks to do IO on the proper scheduler
52
55
* and then move them back to their home.
53
56
*/
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
+
59
60
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
+ }
67
76
}
77
+ old. expect ( "No old home because task had already been killed." )
68
78
}
79
+ }
69
80
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 ;
72
84
73
- // unhome home
85
+ let old = Cell :: new ( old ) ;
74
86
do task:: unkillable { // FIXME(#8674)
75
87
let scheduler : ~Scheduler = Local :: take ( ) ;
76
88
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
+ */
77
94
do task. wake ( ) . map_move |mut task| {
78
- task. give_home( old_home . take( ) ) ;
95
+ task. give_home ( old . take ( ) ) ;
79
96
scheduler. make_handle ( ) . send ( TaskFromFriend ( task) ) ;
80
97
} ;
81
98
}
82
99
}
83
-
84
- // return the result of the IO
85
- a
86
100
}
87
101
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
+ }
103
108
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
+ }
107
116
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)
109
120
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
120
125
}
121
126
}
122
127
0 commit comments