@@ -14,7 +14,8 @@ import option = option;
14
14
import option:: some;
15
15
import option:: none;
16
16
import str;
17
- import std:: treemap;
17
+ import std:: map;
18
+ import std:: map:: hashmap;
18
19
import vec;
19
20
import io;
20
21
import io:: { reader_util, writer_util} ;
@@ -30,10 +31,30 @@ import comm::recv;
30
31
import comm:: send;
31
32
import comm:: methods;
32
33
34
+ macro_rules! move {
35
+ { $x: expr } => { unsafe { let y <- * ptr:: addr_of( $x) ; y } }
36
+ }
37
+
33
38
trait word_reader {
34
39
fn read_word ( ) -> option < str > ;
35
40
}
36
41
42
+ trait hash_key {
43
+ fn hash ( ) -> uint ;
44
+ fn eq ( self ) -> bool ;
45
+ }
46
+
47
+ fn mk_hash < K : const hash_key , V : copy > ( ) -> map:: hashmap < K , V > {
48
+ fn hashfn < K : const hash_key > ( k : K ) -> uint { k. hash ( ) }
49
+
50
+ map:: hashmap ( hashfn :: < K > , |x, y| x. eq ( y) )
51
+ }
52
+
53
+ impl of hash_key for str {
54
+ fn hash ( ) -> uint { str:: hash ( self ) }
55
+ fn eq ( & & x: str ) -> bool { str:: eq ( self , x) }
56
+ }
57
+
37
58
// These used to be in task, but they disappeard.
38
59
type joinable_task = port < ( ) > ;
39
60
fn spawn_joinable ( +f : fn ~( ) ) -> joinable_task {
@@ -79,6 +100,23 @@ fn reduce(&&word: str, get: map_reduce::getter<int>) {
79
100
io:: println ( #fmt ( "%s\t %?" , word, count) ) ;
80
101
}
81
102
103
+ class box<T > {
104
+ let mut contents: option < T > ;
105
+ new( +x: T ) { self . contents = some ( x) ; }
106
+
107
+ fn swap ( f : fn ( +T ) -> T ) {
108
+ let mut tmp = none;
109
+ self . contents <-> tmp;
110
+ self . contents = some ( f ( option:: unwrap ( tmp) ) ) ;
111
+ }
112
+
113
+ fn unwrap ( ) -> T {
114
+ let mut tmp = none;
115
+ self . contents <-> tmp;
116
+ option:: unwrap ( tmp)
117
+ }
118
+ }
119
+
82
120
mod map_reduce {
83
121
export putter;
84
122
export getter;
@@ -99,54 +137,74 @@ mod map_reduce {
99
137
mapper_done
100
138
}
101
139
140
+
141
+ proto ! ctrl_proto {
142
+ open: send<K : copy send, V : copy send> {
143
+ find_reducer( K ) -> reducer_response<K , V >,
144
+ mapper_done -> terminated
145
+ }
146
+
147
+ reducer_response: recv<K : copy send, V : copy send> {
148
+ reducer( chan<reduce_proto<V >>) -> open<K , V >
149
+ }
150
+
151
+ terminated: send { }
152
+ }
153
+
102
154
enum reduce_proto < V : copy send> { emit_val( V ) , done, ref, release }
103
155
104
- fn start_mappers < K1 : copy send, K2 : copy send, V : copy send> (
156
+ fn start_mappers < K1 : copy send, K2 : const copy send hash_key ,
157
+ V : copy send> (
105
158
map : mapper < K1 , K2 , V > ,
106
- ctrl : chan < ctrl_proto < K2 , V > > , inputs : ~[ K1 ] )
159
+ & ctrls: ~[ ctrl_proto:: server:: open < K2 , V > ] ,
160
+ inputs : ~[ K1 ] )
107
161
-> ~[ joinable_task ]
108
162
{
109
163
let mut tasks = ~[ ] ;
110
164
for inputs. each |i| {
165
+ let ( ctrl, ctrl_server) = ctrl_proto:: init ( ) ;
166
+ let ctrl = box ( ctrl) ;
111
167
vec:: push ( tasks, spawn_joinable ( || map_task ( map, ctrl, i) ) ) ;
168
+ vec:: push ( ctrls, ctrl_server) ;
112
169
}
113
170
ret tasks;
114
171
}
115
172
116
- fn map_task < K1 : copy send, K2 : copy send, V : copy send> (
173
+ fn map_task< K1 : copy send, K2 : const copy send hash_key , V : copy send> (
117
174
map : mapper < K1 , K2 , V > ,
118
- ctrl : chan < ctrl_proto < K2 , V > > ,
175
+ ctrl : box < ctrl_proto:: client :: open < K2 , V > > ,
119
176
input : K1 )
120
177
{
121
178
// log(error, "map_task " + input);
122
- let intermediates = treemap :: treemap ( ) ;
179
+ let intermediates = mk_hash ( ) ;
123
180
124
- fn emit < K2 : copy send, V : copy send> (
125
- im : treemap:: treemap < K2 , chan < reduce_proto < V > > > ,
126
- ctrl : chan < ctrl_proto < K2 , V > > , key : K2 , val : V )
127
- {
128
- let c;
129
- alt treemap:: find ( im, key) {
130
- some ( _c) { c = _c; }
181
+ do map( input) |key, val| {
182
+ let mut c = none;
183
+ alt intermediates. find ( key) {
184
+ some ( _c) { c = some ( _c) ; }
131
185
none {
132
- let p = port ( ) ;
133
- send ( ctrl, find_reducer ( key, chan ( p) ) ) ;
134
- c = recv ( p) ;
135
- treemap:: insert ( im, key, c) ;
136
- send ( c, ref) ;
186
+ do ctrl. swap |ctrl| {
187
+ let ctrl = ctrl_proto:: client:: find_reducer ( ctrl, key) ;
188
+ alt pipes:: recv ( ctrl) {
189
+ ctrl_proto:: reducer ( c_, ctrl) {
190
+ c = some ( c_) ;
191
+ move !{ ctrl}
192
+ }
193
+ }
194
+ }
195
+ intermediates. insert ( key, c. get ( ) ) ;
196
+ send ( c. get ( ) , ref) ;
137
197
}
138
198
}
139
- send ( c, emit_val ( val) ) ;
199
+ send ( c. get ( ) , emit_val ( val) ) ;
140
200
}
141
201
142
- map ( input, { |a, b|emit ( intermediates, ctrl, a, b) } ) ;
143
-
144
202
fn finish < K : copy send, V : copy send> ( _k : K , v : chan < reduce_proto < V > > )
145
203
{
146
204
send ( v, release) ;
147
205
}
148
- treemap :: traverse ( intermediates, finish ) ;
149
- send ( ctrl, mapper_done ) ;
206
+ for intermediates. each_value |v| { send ( v , release ) }
207
+ ctrl_proto :: client :: mapper_done ( ctrl. unwrap ( ) ) ;
150
208
}
151
209
152
210
fn reduce_task < K : copy send, V : copy send> (
@@ -184,30 +242,32 @@ mod map_reduce {
184
242
reduce( key, || get( p, ref_count, is_done) ) ;
185
243
}
186
244
187
- fn map_reduce < K1 : copy send, K2 : copy send, V : copy send> (
245
+ fn map_reduce < K1 : copy send, K2 : const copy send hash_key , V : copy send> (
188
246
map: mapper < K1 , K2 , V > ,
189
247
reduce: reducer < K2 , V > ,
190
248
inputs: ~[ K1 ] )
191
249
{
192
- let ctrl = port ( ) ;
250
+ let mut ctrl = ~ [ ] ;
193
251
194
252
// This task becomes the master control task. It task::_spawns
195
253
// to do the rest.
196
254
197
- let reducers = treemap :: treemap ( ) ;
198
- let mut tasks = start_mappers ( map, chan ( ctrl) , inputs) ;
255
+ let reducers = mk_hash ( ) ;
256
+ let mut tasks = start_mappers( map, ctrl, inputs) ;
199
257
let mut num_mappers = vec:: len( inputs) as int;
200
258
201
259
while num_mappers > 0 {
202
- alt recv ( ctrl) {
203
- mapper_done {
260
+ let ( _ready, message, ctrls) = pipes:: select( ctrl) ;
261
+ alt option:: unwrap( message) {
262
+ ctrl_proto:: mapper_done( _) {
204
263
// #error("received mapper terminated.");
205
264
num_mappers -= 1 ;
265
+ ctrl = ctrls;
206
266
}
207
- find_reducer ( k, cc) {
267
+ ctrl_proto :: find_reducer( k, cc) {
208
268
let c;
209
269
// log(error, "finding reducer for " + k);
210
- alt treemap :: find ( reducers , k) {
270
+ alt reducers . find( k) {
211
271
some( _c) {
212
272
// log(error,
213
273
// "reusing existing reducer for " + k);
@@ -221,19 +281,17 @@ mod map_reduce {
221
281
vec:: push( tasks,
222
282
spawn_joinable( || reduce_task( r, kk, ch) ) ) ;
223
283
c = recv( p) ;
224
- treemap :: insert ( reducers , k, c) ;
284
+ reducers . insert( k, c) ;
225
285
}
226
286
}
227
- send ( cc, c) ;
287
+ ctrl = vec:: append_one(
288
+ ctrls,
289
+ ctrl_proto:: server:: reducer( move ! { cc} , c) ) ;
228
290
}
229
291
}
230
292
}
231
293
232
- fn finish < K : copy send, V : copy send> ( _k : K , v : chan < reduce_proto < V > > )
233
- {
234
- send ( v, done) ;
235
- }
236
- treemap:: traverse ( reducers, finish) ;
294
+ for reducers. each_value |v| { send( v, done) }
237
295
238
296
for tasks. each |t| { join( t) ; }
239
297
}
@@ -254,7 +312,7 @@ fn main(argv: ~[str]) {
254
312
}
255
313
else {
256
314
let num_readers = 50 ;
257
- let words_per_reader = 1000 ;
315
+ let words_per_reader = 600 ;
258
316
vec:: from_fn(
259
317
num_readers,
260
318
|_i| fn~( ) -> word_reader {
@@ -301,7 +359,8 @@ class random_word_reader: word_reader {
301
359
fn read_word( ) -> option < str > {
302
360
if self. remaining > 0 {
303
361
self . remaining -= 1 ;
304
- some ( self . rng . gen_str ( 5 ) )
362
+ let len = self . rng. gen_uint_range( 1 , 4 ) ;
363
+ some( self . rng. gen_str( len) )
305
364
}
306
365
else { none }
307
366
}
0 commit comments