@@ -13,7 +13,10 @@ use std::mem;
13
13
use std:: rc:: { Rc , Weak } ;
14
14
15
15
use task:: { self , Task } ;
16
- use { Async , AsyncSink , Poll , StartSend , Sink , Stream } ;
16
+ use future:: Executor ;
17
+ use sink:: SendAll ;
18
+ use resultstream:: { self , Results } ;
19
+ use { Async , AsyncSink , Future , Poll , StartSend , Sink , Stream } ;
17
20
18
21
/// Creates a bounded in-memory channel with buffered storage.
19
22
///
@@ -330,3 +333,125 @@ impl<T> SendError<T> {
330
333
self . 0
331
334
}
332
335
}
336
+
337
+ /// Handle returned from the `spawn` function.
338
+ ///
339
+ /// This handle is a stream that proxies a stream on a seperate `Executor`.
340
+ /// Created through the `mpsc::spawn` function, this handle will produce
341
+ /// the same values as the proxied stream, as they are produced in the executor,
342
+ /// and uses a limited buffer to exert back-pressure on the remote stream.
343
+ ///
344
+ /// If this handle is dropped, then the stream will no longer be polled and is
345
+ /// scheduled to be dropped.
346
+ pub struct SpawnHandle < Item , Error > {
347
+ inner : Receiver < Result < Item , Error > >
348
+ }
349
+
350
+ /// Type of future which `Executor` instances must be able to execut for `spawn`.
351
+ pub struct Execute < S : Stream > {
352
+ inner : SendAll < Sender < Result < S :: Item , S :: Error > > , Results < S , SendError < Result < S :: Item , S :: Error > > > >
353
+ }
354
+
355
+ /// Spawns a `stream` onto the instance of `Executor` provided, `executor`,
356
+ /// returning a handle representing the remote stream.
357
+ ///
358
+ /// The `stream` will be canceled if the `SpawnHandle` is dropped.
359
+ ///
360
+ /// The `SpawnHandle` returned is a stream that is a proxy for `stream` itself.
361
+ /// When `stream` has additional items available, then the `SpawnHandle`
362
+ /// will have those same items available.
363
+ ///
364
+ /// At most `buffer + 1` elements will be buffered at a time. If the buffer
365
+ /// is full, then `stream` will stop progressing until more space is available.
366
+ /// This allows the `SpawnHandle` to exert backpressure on the `stream`.
367
+ ///
368
+ /// # Panics
369
+ ///
370
+ /// This function will panic if `executor` is unable spawn a `Future` containing
371
+ /// the entirety of the `stream`.
372
+ pub fn spawn < S , E > ( stream : S , executor : & E , buffer : usize ) -> SpawnHandle < S :: Item , S :: Error >
373
+ where S : Stream ,
374
+ E : Executor < Execute < S > >
375
+ {
376
+ let ( tx, rx) = channel ( buffer) ;
377
+ executor. execute ( Execute {
378
+ inner : tx. send_all ( resultstream:: new ( stream) )
379
+ } ) . expect ( "failed to spawn stream" ) ;
380
+ SpawnHandle {
381
+ inner : rx
382
+ }
383
+ }
384
+
385
+ /// Spawns a `stream` onto the instance of `Executor` provided, `executor`,
386
+ /// returning a handle representing the remote stream, with unbounded buffering.
387
+ ///
388
+ /// The `stream` will be canceled if the `SpawnHandle` is dropped.
389
+ ///
390
+ /// The `SpawnHandle` returned is a stream that is a proxy for `stream` itself.
391
+ /// When `stream` has additional items available, then the `SpawnHandle`
392
+ /// will have those same items available.
393
+ ///
394
+ /// An unbounded buffer is used, which means that values will be buffered as
395
+ /// fast as `stream` can produce them, without any backpressure. Therefore, if
396
+ /// `stream` is an infinite stream, it can use an unbounded amount of memory, and
397
+ /// potentially hog CPU resources. In particular, if `stream` is infinite
398
+ /// and doesn't ever yield (by returnin `Async::NotReady` from `poll`), it
399
+ /// will result in an infinite loop.
400
+ ///
401
+ /// # Panics
402
+ ///
403
+ /// This function will panic if `executor` is unable spawn a `Future` containing
404
+ /// the entirety of the `stream`.
405
+ pub fn spawn_unbounded < S , E > ( stream : S , executor : & E ) -> SpawnHandle < S :: Item , S :: Error >
406
+ where S : Stream ,
407
+ E : Executor < Execute < S > >
408
+ {
409
+ let ( tx, rx) = channel_ ( None ) ;
410
+ executor. execute ( Execute {
411
+ inner : tx. send_all ( resultstream:: new ( stream) )
412
+ } ) . expect ( "failed to spawn stream" ) ;
413
+ SpawnHandle {
414
+ inner : rx
415
+ }
416
+ }
417
+
418
+ impl < I , E > Stream for SpawnHandle < I , E > {
419
+ type Item = I ;
420
+ type Error = E ;
421
+
422
+ fn poll ( & mut self ) -> Poll < Option < I > , E > {
423
+ match self . inner . poll ( ) {
424
+ Ok ( Async :: Ready ( Some ( Ok ( t) ) ) ) => Ok ( Async :: Ready ( Some ( t. into ( ) ) ) ) ,
425
+ Ok ( Async :: Ready ( Some ( Err ( e) ) ) ) => Err ( e) ,
426
+ Ok ( Async :: Ready ( None ) ) => Ok ( Async :: Ready ( None ) ) ,
427
+ Ok ( Async :: NotReady ) => Ok ( Async :: NotReady ) ,
428
+ Err ( _) => unreachable ! ( "mpsc::Receiver should never return Err" ) ,
429
+ }
430
+ }
431
+ }
432
+
433
+ impl < I , E > fmt:: Debug for SpawnHandle < I , E > {
434
+ fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
435
+ f. debug_struct ( "SpawnHandle" )
436
+ . finish ( )
437
+ }
438
+ }
439
+
440
+ impl < S : Stream > Future for Execute < S > {
441
+ type Item = ( ) ;
442
+ type Error = ( ) ;
443
+
444
+ fn poll ( & mut self ) -> Poll < ( ) , ( ) > {
445
+ match self . inner . poll ( ) {
446
+ Ok ( Async :: NotReady ) => Ok ( Async :: NotReady ) ,
447
+ _ => Ok ( Async :: Ready ( ( ) ) )
448
+ }
449
+ }
450
+ }
451
+
452
+ impl < S : Stream > fmt:: Debug for Execute < S > {
453
+ fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
454
+ f. debug_struct ( "Execute" )
455
+ . finish ( )
456
+ }
457
+ }
0 commit comments