@@ -44,6 +44,7 @@ export get_task;
44
44
export spawn;
45
45
export spawn_joinable;
46
46
export spawn_connected;
47
+ export spawn_sched;
47
48
export connected_fn;
48
49
export connected_task;
49
50
export currently_unwinding;
@@ -62,10 +63,15 @@ type rust_closure = {
62
63
#[ link_name = "rustrt" ]
63
64
#[ abi = "cdecl" ]
64
65
native mod rustrt {
66
+ fn rust_get_sched_id ( ) -> sched_id ;
67
+ fn rust_new_sched ( num_threads : c:: uintptr_t ) -> sched_id ;
68
+
65
69
fn get_task_id ( ) -> task_id ;
66
70
fn rust_get_task ( ) -> * rust_task ;
67
71
68
72
fn new_task ( ) -> task_id ;
73
+ fn rust_new_task_in_sched ( id : sched_id ) -> task_id ;
74
+
69
75
fn drop_task ( task_id : * rust_task ) ;
70
76
fn get_task_pointer ( id : task_id ) -> * rust_task ;
71
77
@@ -85,6 +91,7 @@ type rust_task =
85
91
86
92
resource rust_task_ptr ( task: * rust_task) { rustrt:: drop_task ( task) ; }
87
93
94
+ type sched_id = int ;
88
95
type task_id = int ;
89
96
90
97
/*
@@ -111,14 +118,17 @@ Returns:
111
118
A handle to the new task
112
119
*/
113
120
fn spawn ( +f : fn ~( ) ) -> task {
114
- spawn_inner ( f, none)
121
+ spawn_inner ( f, none, new_task_in_this_sched )
115
122
}
116
123
117
- fn spawn_inner ( -f : fn ~( ) ,
118
- notify : option < comm:: chan < task_notification > > ) -> task unsafe {
124
+ fn spawn_inner (
125
+ -f : fn ~( ) ,
126
+ notify : option < comm:: chan < task_notification > > ,
127
+ new_task : fn ( ) -> task_id
128
+ ) -> task unsafe {
119
129
let closure: * rust_closure = unsafe :: reinterpret_cast ( ptr:: addr_of ( f) ) ;
120
130
#debug ( "spawn: closure={%x,%x}" , ( * closure) . fnptr , ( * closure) . envptr ) ;
121
- let id = rustrt :: new_task ( ) ;
131
+ let id = new_task ( ) ;
122
132
123
133
// set up notifications if they are enabled.
124
134
option:: may ( notify) { |c|
@@ -132,6 +142,39 @@ fn spawn_inner(-f: fn~(),
132
142
ret id;
133
143
}
134
144
145
+ fn new_task_in_this_sched ( ) -> task_id {
146
+ rustrt:: new_task ( )
147
+ }
148
+
149
+ fn new_task_in_new_sched ( num_threads : uint ) -> task_id {
150
+ let sched_id = rustrt:: rust_new_sched ( num_threads) ;
151
+ rustrt:: rust_new_task_in_sched ( sched_id)
152
+ }
153
+
154
+ /*
155
+ Function: spawn_sched
156
+
157
+ Creates a new scheduler and executes a task on it. Tasks subsequently
158
+ spawned by that task will also execute on the new scheduler. When
159
+ there are no more tasks to execute the scheduler terminates.
160
+
161
+ Arguments:
162
+
163
+ num_threads - The number of OS threads to dedicate schedule tasks on
164
+ f - A unique closure to execute as a task on the new scheduler
165
+
166
+ Failure:
167
+
168
+ The number of threads must be greater than 0
169
+
170
+ */
171
+ fn spawn_sched ( num_threads : uint , +f : fn ~( ) ) -> task {
172
+ if num_threads < 1 u {
173
+ fail "Can not create a scheduler with no threads" ;
174
+ }
175
+ spawn_inner ( f, none, bind new_task_in_new_sched ( num_threads) )
176
+ }
177
+
135
178
/*
136
179
Type: joinable_task
137
180
@@ -142,7 +185,7 @@ type joinable_task = (task, comm::port<task_notification>);
142
185
fn spawn_joinable ( +f : fn ~( ) ) -> joinable_task {
143
186
let notify_port = comm:: port ( ) ;
144
187
let notify_chan = comm:: chan ( notify_port) ;
145
- let task = spawn_inner ( f, some ( notify_chan) ) ;
188
+ let task = spawn_inner ( f, some ( notify_chan) , new_task_in_this_sched ) ;
146
189
ret ( task, notify_port) ;
147
190
/*
148
191
resource notify_rsrc(data: (comm::chan<task_notification>,
@@ -411,6 +454,56 @@ mod tests {
411
454
_ { fail; }
412
455
}
413
456
}
457
+
458
+ #[ test]
459
+ #[ should_fail]
460
+ #[ ignore( cfg( target_os = "win32" ) ) ]
461
+ fn spawn_sched_no_threads ( ) {
462
+ spawn_sched ( 0 u) { || } ;
463
+ }
464
+
465
+ #[ test]
466
+ fn spawn_sched_1 ( ) {
467
+ let po = comm:: port ( ) ;
468
+ let ch = comm:: chan ( po) ;
469
+
470
+ fn f ( i : int , ch : comm:: chan < ( ) > ) {
471
+ let parent_sched_id = rustrt:: rust_get_sched_id ( ) ;
472
+
473
+ spawn_sched ( 1 u) { ||
474
+ let child_sched_id = rustrt:: rust_get_sched_id ( ) ;
475
+ assert parent_sched_id != child_sched_id;
476
+
477
+ if ( i == 0 ) {
478
+ comm:: send ( ch, ( ) ) ;
479
+ } else {
480
+ f ( i - 1 , ch) ;
481
+ }
482
+ } ;
483
+
484
+ }
485
+ f ( 10 , ch) ;
486
+ comm:: recv ( po) ;
487
+ }
488
+
489
+ #[ test]
490
+ fn spawn_sched_childs_on_same_sched ( ) {
491
+ let po = comm:: port ( ) ;
492
+ let ch = comm:: chan ( po) ;
493
+
494
+ spawn_sched ( 1 u) { ||
495
+ let parent_sched_id = rustrt:: rust_get_sched_id ( ) ;
496
+ spawn { ||
497
+ let child_sched_id = rustrt:: rust_get_sched_id ( ) ;
498
+ // This should be on the same scheduler
499
+ assert parent_sched_id == child_sched_id;
500
+ comm:: send ( ch, ( ) ) ;
501
+ } ;
502
+ } ;
503
+
504
+ comm:: recv ( po) ;
505
+ }
506
+
414
507
}
415
508
416
509
0 commit comments