1
1
use std:: sync:: mpsc;
2
2
use std:: thread;
3
3
4
+
4
5
#[ derive( Debug ) ]
5
6
pub struct Pipeline < Output >
6
7
where Output : Send + ' static
7
8
{
8
9
rx : mpsc:: Receiver < Output > ,
9
10
}
10
11
12
+
11
13
impl < Output > Pipeline < Output >
12
14
where Output : Send
13
15
{
@@ -73,6 +75,7 @@ impl<Output> Pipeline<Output>
73
75
}
74
76
}
75
77
78
+
76
79
impl < Output > IntoIterator for Pipeline < Output >
77
80
where Output : Send
78
81
{
@@ -85,6 +88,7 @@ impl<Output> IntoIterator for Pipeline<Output>
85
88
}
86
89
}
87
90
91
+
88
92
pub trait PipelineEntry < In , Out > {
89
93
fn process < I : IntoIterator < Item = In > > ( self ,
90
94
rx : I ,
@@ -134,8 +138,22 @@ pub mod map {
134
138
}
135
139
}
136
140
}
141
+
142
+ impl < In , Out , Func > Clone for Mapper < In , Out , Func >
143
+ where Func : Fn ( In ) -> Out + Copy
144
+ {
145
+ fn clone ( & self ) -> Self {
146
+ Mapper :: new ( self . func )
147
+ }
148
+ }
149
+
150
+ impl < In , Out , Func > Copy for Mapper < In , Out , Func >
151
+ where Func : Fn ( In ) -> Out + Copy
152
+ {
153
+ }
137
154
}
138
155
156
+
139
157
pub mod filter {
140
158
use std:: marker:: PhantomData ;
141
159
use std:: sync:: mpsc;
@@ -180,6 +198,10 @@ pub mod filter {
180
198
181
199
182
200
pub mod multiplex {
201
+ // work around https://github.com/rust-lang/rust/issues/28229
202
+ // (functions implement Copy but not Clone)
203
+ #![ cfg_attr( feature="cargo-clippy" , allow( expl_impl_clone_on_copy) ) ]
204
+
183
205
use std:: marker:: PhantomData ;
184
206
use std:: sync:: mpsc;
185
207
use std:: sync:: { Arc , Mutex } ;
@@ -189,7 +211,7 @@ pub mod multiplex {
189
211
190
212
#[ derive( Debug ) ]
191
213
pub struct Multiplex < In , Out , Entry >
192
- where Entry : PipelineEntry < In , Out >
214
+ where Entry : PipelineEntry < In , Out > + Send
193
215
{
194
216
entries : Vec < Entry > ,
195
217
buffsize : usize ,
@@ -199,6 +221,14 @@ pub mod multiplex {
199
221
out_ : PhantomData < Out > ,
200
222
}
201
223
224
+ impl < In , Out , Entry > Multiplex < In , Out , Entry >
225
+ where Entry : PipelineEntry < In , Out > + Send + Copy
226
+ {
227
+ pub fn from ( entry : Entry , workers : usize , buffsize : usize ) -> Self {
228
+ Self :: new ( ( 0 ..workers) . map ( |_| entry) . collect ( ) , buffsize)
229
+ }
230
+ }
231
+
202
232
impl < In , Out , Entry > Multiplex < In , Out , Entry >
203
233
where Entry : PipelineEntry < In , Out > + Send
204
234
{
@@ -324,21 +354,59 @@ mod tests {
324
354
assert_eq ! ( produced, expect) ;
325
355
}
326
356
357
+ // just something expensive
358
+ fn fib_work ( n : u64 ) -> u64 {
359
+ const WORK_FACTOR : u64 = 10 ;
360
+ fib ( WORK_FACTOR ) + n
361
+ }
362
+
363
+ fn fib ( n : u64 ) -> u64 {
364
+ if n == 0 || n == 1 {
365
+ 1
366
+ } else {
367
+ fib ( n - 1 ) + fib ( n - 2 )
368
+ }
369
+ }
370
+
371
+ #[ test]
372
+ fn multiplex_map_function ( ) {
373
+ // we have two signatures for Multiplex, one that takes a function
374
+ // pointer and one that can take a closure. THis is the function pointer
375
+ // side
376
+
377
+ let buffsize: usize = 10 ;
378
+ let workers: usize = 10 ;
379
+
380
+ let source: Vec < u64 > = ( 1 ..1000 ) . collect ( ) ;
381
+ let expect: Vec < u64 > =
382
+ source. clone ( ) . into_iter ( ) . map ( fib_work) . collect ( ) ;
383
+
384
+ let pbb: Pipeline < u64 > = Pipeline :: new ( source, buffsize)
385
+ . then ( multiplex:: Multiplex :: from ( map:: Mapper :: new ( fib_work) ,
386
+ workers,
387
+ buffsize) ,
388
+ buffsize) ;
389
+ let mut produced: Vec < u64 > = pbb. into_iter ( ) . collect ( ) ;
390
+
391
+ produced. sort ( ) ; // these may arrive out of order
392
+ assert_eq ! ( produced, expect) ;
393
+ }
394
+
327
395
#[ test]
328
- fn multiplex_map ( ) {
396
+ fn multiplex_map_closure ( ) {
329
397
let buffsize: usize = 10 ;
398
+ let workers: usize = 10 ;
330
399
331
400
let source: Vec < i32 > = ( 1 ..1000 ) . collect ( ) ;
332
401
let expect: Vec < i32 > = source. iter ( ) . map ( |x| x * 2 ) . collect ( ) ;
333
402
334
403
let pbb: Pipeline < i32 > = Pipeline :: new ( source, buffsize)
335
- // TOOD multiplex takes a list of PipelineEntry but it would be
336
- // nicer if it just took one and was able to clone it
337
- . then (
338
- multiplex:: Multiplex :: new (
339
- ( 0 ..10 ) . map ( |_| map:: Mapper :: new ( |i| i* 2 ) ) . collect ( ) ,
340
- buffsize) ,
341
- buffsize) ;
404
+ . then ( multiplex:: Multiplex :: new ( ( 0 ..workers)
405
+ . map ( |_| {
406
+ map:: Mapper :: new ( |i| i * 2 )
407
+ } ) . collect ( ) ,
408
+ buffsize) ,
409
+ buffsize) ;
342
410
let mut produced: Vec < i32 > = pbb. into_iter ( ) . collect ( ) ;
343
411
344
412
produced. sort ( ) ; // these may arrive out of order
0 commit comments