@@ -14,15 +14,16 @@ use cast::transmute;
14
14
15
15
use super :: work_queue:: WorkQueue ;
16
16
use super :: stack:: { StackPool , StackSegment } ;
17
- use super :: rtio:: { EventLoop , EventLoopObject , IoFactoryObject } ;
17
+ use super :: rtio:: { EventLoop , EventLoopObject } ;
18
18
use super :: context:: Context ;
19
19
20
20
#[ cfg( test) ] use super :: uvio:: UvEventLoop ;
21
21
#[ cfg( test) ] use unstable:: run_in_bare_thread;
22
22
#[ cfg( test) ] use int;
23
23
#[ cfg( test) ] use cell:: Cell ;
24
24
25
- mod local;
25
+ // A more convenient name for external callers, e.g. `local_sched::take()`
26
+ pub mod local_sched;
26
27
27
28
/// The Scheduler is responsible for coordinating execution of Tasks
28
29
/// on a single thread. When the scheduler is running it is owned by
@@ -90,52 +91,25 @@ pub impl Scheduler {
90
91
assert ! ( !self . in_task_context( ) ) ;
91
92
92
93
// Give ownership of the scheduler (self) to the thread
93
- local:: put ( self ) ;
94
-
95
- let scheduler = unsafe { local:: borrow ( ) } ;
96
- fn run_scheduler_once ( ) {
97
- let scheduler = Scheduler :: take_local ( ) ;
98
- if scheduler. resume_task_from_queue ( ) {
99
- // Ok, a task ran. Nice! We'll do it again later
100
- do Scheduler :: borrow_local |scheduler| {
101
- scheduler. event_loop . callback ( run_scheduler_once) ;
94
+ local_sched:: put ( self ) ;
95
+
96
+ unsafe {
97
+ let scheduler = local_sched:: unsafe_borrow ( ) ;
98
+ fn run_scheduler_once ( ) {
99
+ let scheduler = local_sched:: take ( ) ;
100
+ if scheduler. resume_task_from_queue ( ) {
101
+ // Ok, a task ran. Nice! We'll do it again later
102
+ do local_sched:: borrow |scheduler| {
103
+ scheduler. event_loop . callback ( run_scheduler_once) ;
104
+ }
102
105
}
103
106
}
104
- }
105
-
106
- scheduler. event_loop . callback ( run_scheduler_once) ;
107
- scheduler. event_loop . run ( ) ;
108
-
109
- return local:: take ( ) ;
110
- }
111
107
112
- /// Get a mutable pointer to the thread-local I/O
113
- /// # Safety Note
114
- /// This allows other mutable aliases to the scheduler, both in the current
115
- /// execution context and other execution contexts.
116
- unsafe fn borrow_local_io ( ) -> & mut IoFactoryObject {
117
- unsafe {
118
- let io = local:: borrow ( ) . event_loop . io ( ) . unwrap ( ) ;
119
- transmute :: < & mut IoFactoryObject , & mut IoFactoryObject > ( io)
108
+ scheduler. event_loop . callback ( run_scheduler_once) ;
109
+ scheduler. event_loop . run ( ) ;
120
110
}
121
- }
122
-
123
- /// Borrow the thread-local scheduler from thread-local storage.
124
- /// While the scheduler is borrowed it is not available in TLS.
125
- fn borrow_local ( f : & fn ( & mut Scheduler ) ) {
126
- let mut sched = local:: take ( ) ;
127
- f ( sched) ;
128
- local:: put ( sched) ;
129
- }
130
-
131
- /// Take ownership of the scheduler from thread local storage
132
- fn take_local ( ) -> ~Scheduler {
133
- local:: take ( )
134
- }
135
111
136
- /// Just check whether there is a local scheduler
137
- fn have_local ( ) -> bool {
138
- local:: exists ( )
112
+ return local_sched:: take ( ) ;
139
113
}
140
114
141
115
// * Scheduler-context operations
@@ -151,7 +125,7 @@ pub impl Scheduler {
151
125
}
152
126
None => {
153
127
rtdebug ! ( "no tasks in queue" ) ;
154
- local :: put ( self ) ;
128
+ local_sched :: put ( self ) ;
155
129
return false ;
156
130
}
157
131
}
@@ -167,22 +141,24 @@ pub impl Scheduler {
167
141
self . current_task = Some ( task) ;
168
142
self . enqueue_cleanup_job ( DoNothing ) ;
169
143
170
- local :: put ( self ) ;
144
+ local_sched :: put ( self ) ;
171
145
172
146
// Take pointers to both the task and scheduler's saved registers.
173
- let sched = unsafe { local:: borrow ( ) } ;
174
- let ( sched_context, _, next_task_context) = sched. get_contexts ( ) ;
175
- let next_task_context = next_task_context. unwrap ( ) ;
176
- // Context switch to the task, restoring it's registers
177
- // and saving the scheduler's
178
- Context :: swap ( sched_context, next_task_context) ;
179
-
180
- let sched = unsafe { local:: borrow ( ) } ;
181
- // The running task should have passed ownership elsewhere
182
- assert ! ( sched. current_task. is_none( ) ) ;
183
-
184
- // Running tasks may have asked us to do some cleanup
185
- sched. run_cleanup_job ( ) ;
147
+ unsafe {
148
+ let sched = local_sched:: unsafe_borrow ( ) ;
149
+ let ( sched_context, _, next_task_context) = sched. get_contexts ( ) ;
150
+ let next_task_context = next_task_context. unwrap ( ) ;
151
+ // Context switch to the task, restoring it's registers
152
+ // and saving the scheduler's
153
+ Context :: swap ( sched_context, next_task_context) ;
154
+
155
+ let sched = local_sched:: unsafe_borrow ( ) ;
156
+ // The running task should have passed ownership elsewhere
157
+ assert ! ( sched. current_task. is_none( ) ) ;
158
+
159
+ // Running tasks may have asked us to do some cleanup
160
+ sched. run_cleanup_job ( ) ;
161
+ }
186
162
}
187
163
188
164
@@ -199,9 +175,9 @@ pub impl Scheduler {
199
175
let dead_task = self . current_task . swap_unwrap ( ) ;
200
176
self . enqueue_cleanup_job ( RecycleTask ( dead_task) ) ;
201
177
202
- local :: put ( self ) ;
178
+ local_sched :: put ( self ) ;
203
179
204
- let sched = unsafe { local :: borrow ( ) } ;
180
+ let sched = unsafe { local_sched :: unsafe_borrow ( ) } ;
205
181
let ( sched_context, last_task_context, _) = sched. get_contexts ( ) ;
206
182
let last_task_context = last_task_context. unwrap ( ) ;
207
183
Context :: swap ( last_task_context, sched_context) ;
@@ -228,15 +204,15 @@ pub impl Scheduler {
228
204
let f_opaque = ClosureConverter :: from_fn ( f_fake_region) ;
229
205
self . enqueue_cleanup_job ( GiveTask ( blocked_task, f_opaque) ) ;
230
206
231
- local :: put ( self ) ;
207
+ local_sched :: put ( self ) ;
232
208
233
- let sched = unsafe { local :: borrow ( ) } ;
209
+ let sched = unsafe { local_sched :: unsafe_borrow ( ) } ;
234
210
let ( sched_context, last_task_context, _) = sched. get_contexts ( ) ;
235
211
let last_task_context = last_task_context. unwrap ( ) ;
236
212
Context :: swap ( last_task_context, sched_context) ;
237
213
238
214
// We could be executing in a different thread now
239
- let sched = unsafe { local :: borrow ( ) } ;
215
+ let sched = unsafe { local_sched :: unsafe_borrow ( ) } ;
240
216
sched. run_cleanup_job ( ) ;
241
217
}
242
218
@@ -253,17 +229,19 @@ pub impl Scheduler {
253
229
self . enqueue_cleanup_job ( RescheduleTask ( old_running_task) ) ;
254
230
self . current_task = Some ( next_task) ;
255
231
256
- local :: put ( self ) ;
232
+ local_sched :: put ( self ) ;
257
233
258
- let sched = unsafe { local:: borrow ( ) } ;
259
- let ( _, last_task_context, next_task_context) = sched. get_contexts ( ) ;
260
- let last_task_context = last_task_context. unwrap ( ) ;
261
- let next_task_context = next_task_context. unwrap ( ) ;
262
- Context :: swap ( last_task_context, next_task_context) ;
263
-
264
- // We could be executing in a different thread now
265
- let sched = unsafe { local:: borrow ( ) } ;
266
- sched. run_cleanup_job ( ) ;
234
+ unsafe {
235
+ let sched = local_sched:: unsafe_borrow ( ) ;
236
+ let ( _, last_task_context, next_task_context) = sched. get_contexts ( ) ;
237
+ let last_task_context = last_task_context. unwrap ( ) ;
238
+ let next_task_context = next_task_context. unwrap ( ) ;
239
+ Context :: swap ( last_task_context, next_task_context) ;
240
+
241
+ // We could be executing in a different thread now
242
+ let sched = local_sched:: unsafe_borrow ( ) ;
243
+ sched. run_cleanup_job ( ) ;
244
+ }
267
245
}
268
246
269
247
// * Other stuff
@@ -363,12 +341,14 @@ pub impl Task {
363
341
// This is the first code to execute after the initial
364
342
// context switch to the task. The previous context may
365
343
// have asked us to do some cleanup.
366
- let sched = unsafe { local:: borrow ( ) } ;
367
- sched. run_cleanup_job ( ) ;
344
+ unsafe {
345
+ let sched = local_sched:: unsafe_borrow ( ) ;
346
+ sched. run_cleanup_job ( ) ;
347
+ }
368
348
369
349
start ( ) ;
370
350
371
- let sched = Scheduler :: take_local ( ) ;
351
+ let sched = local_sched :: take ( ) ;
372
352
sched. terminate_current_task ( ) ;
373
353
} ;
374
354
return wrapper;
@@ -428,7 +408,7 @@ fn test_swap_tasks() {
428
408
let mut sched = ~UvEventLoop :: new_scheduler ( ) ;
429
409
let task1 = ~do Task :: new ( & mut sched. stack_pool ) {
430
410
unsafe { * count_ptr = * count_ptr + 1 ; }
431
- let mut sched = Scheduler :: take_local ( ) ;
411
+ let mut sched = local_sched :: take ( ) ;
432
412
let task2 = ~do Task :: new ( & mut sched. stack_pool ) {
433
413
unsafe { * count_ptr = * count_ptr + 1 ; }
434
414
} ;
@@ -460,7 +440,7 @@ fn test_run_a_lot_of_tasks_queued() {
460
440
assert ! ( count == MAX ) ;
461
441
462
442
fn run_task ( count_ptr : * mut int ) {
463
- do Scheduler :: borrow_local |sched| {
443
+ do local_sched :: borrow |sched| {
464
444
let task = ~do Task :: new ( & mut sched. stack_pool ) {
465
445
unsafe {
466
446
* count_ptr = * count_ptr + 1 ;
@@ -493,7 +473,7 @@ fn test_run_a_lot_of_tasks_direct() {
493
473
assert ! ( count == MAX ) ;
494
474
495
475
fn run_task ( count_ptr : * mut int ) {
496
- let mut sched = Scheduler :: take_local ( ) ;
476
+ let mut sched = local_sched :: take ( ) ;
497
477
let task = ~do Task :: new ( & mut sched. stack_pool ) {
498
478
unsafe {
499
479
* count_ptr = * count_ptr + 1 ;
@@ -513,11 +493,11 @@ fn test_block_task() {
513
493
do run_in_bare_thread {
514
494
let mut sched = ~UvEventLoop : : new_scheduler ( ) ;
515
495
let task = ~do Task :: new ( & mut sched. stack_pool ) {
516
- let sched = Scheduler :: take_local ( ) ;
496
+ let sched = local_sched :: take ( ) ;
517
497
assert ! ( sched. in_task_context( ) ) ;
518
498
do sched. deschedule_running_task_and_then ( ) |task| {
519
499
let task = Cell ( task) ;
520
- do Scheduler :: borrow_local |sched| {
500
+ do local_sched :: borrow |sched| {
521
501
assert ! ( !sched. in_task_context( ) ) ;
522
502
sched. task_queue . push_back ( task. take ( ) ) ;
523
503
}
0 commit comments