@@ -63,11 +63,11 @@ use cell::Cell;
63
63
use clone:: Clone ;
64
64
use container:: Container ;
65
65
use from_str:: FromStr ;
66
+ use iter:: Times ;
66
67
use iterator:: IteratorUtil ;
67
68
use option:: { Some , None } ;
68
69
use os;
69
70
use ptr:: RawPtr ;
70
- use uint;
71
71
use rt:: sched:: { Scheduler , Coroutine , Shutdown } ;
72
72
use rt:: sleeper_list:: SleeperList ;
73
73
use rt:: task:: Task ;
@@ -150,7 +150,7 @@ pub mod local_ptr;
150
150
/// Bindings to pthread/windows thread-local storage.
151
151
pub mod thread_local_storage;
152
152
153
- /// A concurrent data structure with which parent tasks wait on child tasks.
153
+ /// For waiting on child tasks.
154
154
pub mod join_latch;
155
155
156
156
pub mod metrics;
@@ -188,43 +188,58 @@ pub fn init(crate_map: *u8) {
188
188
logging:: init ( crate_map) ;
189
189
}
190
190
191
+ /// One-time runtime cleanup.
191
192
pub fn cleanup ( ) {
192
193
global_heap:: cleanup ( ) ;
193
194
}
194
195
196
+ /// Execute the main function in a scheduler.
197
+ ///
198
+ /// Configures the runtime according to the environment, by default
199
+ /// using a task scheduler with the same number of threads as cores.
200
+ /// Returns a process exit code.
195
201
pub fn run ( main : ~fn ( ) ) -> int {
202
+
196
203
static DEFAULT_ERROR_CODE : int = 101 ;
197
204
198
205
let nthreads = match os:: getenv ( "RUST_THREADS" ) {
199
206
Some ( nstr) => FromStr :: from_str ( nstr) . get ( ) ,
200
207
None => unsafe { util:: num_cpus ( ) }
201
208
} ;
202
209
210
+ // The shared list of sleeping schedulers. Schedulers wake each other
211
+ // occassionally to do new work.
203
212
let sleepers = SleeperList :: new ( ) ;
213
+ // The shared work queue. Temporary until work stealing is implemented.
204
214
let work_queue = WorkQueue :: new ( ) ;
205
215
206
- let mut handles = ~ [ ] ;
216
+ // The schedulers.
207
217
let mut scheds = ~[ ] ;
218
+ // Handles to the schedulers. When the main task ends these will be
219
+ // sent the Shutdown message to terminate the schedulers.
220
+ let mut handles = ~[ ] ;
208
221
209
- for uint:: range( 0 , nthreads) |_| {
222
+ for nthreads . times {
223
+ // Every scheduler is driven by an I/O event loop.
210
224
let loop_ = ~UvEventLoop : : new( ) ;
211
225
let mut sched = ~Scheduler :: new( loop_, work_queue. clone( ) , sleepers. clone( ) ) ;
212
226
let handle = sched. make_handle( ) ;
213
227
214
- handles. push ( handle) ;
215
228
scheds. push( sched) ;
229
+ handles. push( handle) ;
216
230
}
217
231
232
+ // Create a shared cell for transmitting the process exit
233
+ // code from the main task to this function.
218
234
let exit_code = UnsafeAtomicRcBox :: new( AtomicInt :: new( 0 ) ) ;
219
235
let exit_code_clone = exit_code. clone( ) ;
220
236
221
- let main_cell = Cell :: new ( main) ;
237
+ // When the main task exits, after all the tasks in the main
238
+ // task tree, shut down the schedulers and set the exit code.
222
239
let handles = Cell :: new( handles) ;
223
- let mut new_task = ~Task :: new_root ( ) ;
224
240
let on_exit: ~fn ( bool) = |exit_success| {
225
241
226
242
let mut handles = handles. take( ) ;
227
- // Tell schedulers to exit
228
243
for handles. mut_iter( ) . advance |handle| {
229
244
handle. send( Shutdown ) ;
230
245
}
@@ -234,13 +249,17 @@ pub fn run(main: ~fn()) -> int {
234
249
( * exit_code_clone. get( ) ) . store( exit_code, SeqCst ) ;
235
250
}
236
251
} ;
252
+
253
+ // Create and enqueue the main task.
254
+ let main_cell = Cell :: new( main) ;
255
+ let mut new_task = ~Task :: new_root( ) ;
237
256
new_task. on_exit = Some ( on_exit) ;
238
257
let main_task = ~Coroutine :: with_task( & mut scheds[ 0 ] . stack_pool,
239
258
new_task, main_cell. take( ) ) ;
240
259
scheds[ 0 ] . enqueue_task( main_task) ;
241
260
261
+ // Run each scheduler in a thread.
242
262
let mut threads = ~[ ] ;
243
-
244
263
while !scheds. is_empty( ) {
245
264
let sched = scheds. pop( ) ;
246
265
let sched_cell = Cell :: new( sched) ;
@@ -253,8 +272,9 @@ pub fn run(main: ~fn()) -> int {
253
272
}
254
273
255
274
// Wait for schedulers
256
- let _threads = threads;
275
+ { let _threads = threads; }
257
276
277
+ // Return the exit code
258
278
unsafe {
259
279
( * exit_code. get( ) ) . load( SeqCst )
260
280
}
0 commit comments