1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
//! Composition tools

use rotor::mio::EventSet;
use rotor::void::{Void, unreachable};
use rotor::{Machine, Scope, Response};


/// Composes two state machines where of the state machines spawns
/// multiple instances of another one
pub enum Spawn<S: Spawner> {
    Spawner(S),
    Child(S::Child),
}

pub trait Spawner {
    type Child: Machine<Seed=Void>;
    type Seed;

    fn spawn(seed: Self::Seed,
        scope: &mut Scope<<Self::Child as Machine>::Context>)
        -> Response<Self::Child, Void>;
}

impl<T, C, S> Spawner for ::uniform::Uniform<T>
    where T: Spawner<Seed=S> + ::uniform::Action<Seed=S, Context=C>
{
    type Child = T::Child;
    type Seed = <T as Spawner>::Seed;

    fn spawn(seed: <Self as Spawner>::Seed,
        scope: &mut Scope<<<Self as Spawner>::Child as Machine>::Context>)
        -> Response<Self::Child, Void>
    {
        T::spawn(seed, scope)
    }
}

impl<S, C, D> Machine for Spawn<S>
    where S: Spawner<Child=C, Seed=D> + Machine<Context=C::Context, Seed=D>,
          C: Machine<Seed=Void>,
{
    type Context = <S::Child as Machine>::Context;
    type Seed = <S as Spawner>::Seed;

    fn create(seed: <S as Spawner>::Seed, scope: &mut Scope<Self::Context>)
        -> Response<Self, Void>
    {
        S::spawn(seed, scope).wrap(Spawn::Child)
    }
    fn ready(self, events: EventSet, scope: &mut Scope<Self::Context>)
        -> Response<Self, Self::Seed>
    {
        use self::Spawn::*;
        match self {
            Spawner(m) => { m.ready(events, scope).wrap(Spawner) }
            Child(m) => { m.ready(events, scope)
                           .map(Child, |x| unreachable(x)) }
        }
    }
    fn spawned(self, scope: &mut Scope<Self::Context>)
        -> Response<Self, Self::Seed>
    {
        use self::Spawn::*;
        match self {
            Spawner(m) => { m.spawned(scope).wrap(Spawner) }
            Child(m) => { m.spawned(scope).map(Child, |x| unreachable(x)) }
        }
    }
    fn timeout(self, scope: &mut Scope<Self::Context>)
        -> Response<Self, Self::Seed>
    {
        use self::Spawn::*;
        match self {
            Spawner(m) => { m.timeout(scope).wrap(Spawner) }
            Child(m) => { m.timeout(scope).map(Child, |x| unreachable(x)) }
        }
    }
    fn wakeup(self, scope: &mut Scope<Self::Context>)
        -> Response<Self, Self::Seed>
    {
        use self::Spawn::*;
        match self {
            Spawner(m) => { m.wakeup(scope).wrap(Spawner) }
            Child(m) => { m.wakeup(scope).map(Child, |x| unreachable(x)) }
        }
    }
}