Loop Initialization¶
Overview¶
Loop initialization has two stages. First is created by:
let loop_creator = try!(rotor::Loop::new());
And the second is created by:
let loop_instance = loop_creator.instantiate(context)
Then you can run the loop:
try!(loop_instance.run());
As you can see the loop_creator.instantiate(..) takes a context for the
instantiation. This is the key difference between two stages.
There is a shortcut if you want to skip second stage of initialization:
let loop_creator = try!(rotor::Loop::new());
try!(loop_creator.run(context));
Adding State Machines¶
To have something useful of main loop you need to add a state machine to
it. State machine initialization is done via add_machine_with method:
try!(loop_creator.add_machine_with(|scope| {
Ok(Tcp::new(addr, scope))
}));
And in loop instance there is similar method:
try!(loop_instance.add_machine_with(|scope| {
Ok(Tcp::new(addr, scope))
}));
The difference is in the signature of the function:
impl Loop {
fn add_machine_with<F>(&mut self, fun: F)
-> Result<(), SpawnError<()>>
where F: FnOnce(&mut EarlyScope) -> Result<M, Box<Error>>;
}
impl LoopInstance {
fn add_machine_with<F>(&mut self, fun: F)
-> Result<(), SpawnError<()>>
where F: FnOnce(&mut Scope<C>) -> Result<M, Box<Error>>;
}
As you can see the only difference is that loop creator gets EarlyScope
as an argument and latter gets Scope<Context> as an argument:
- Both have
GenericScopeimplementation, so you can have constructors generic over the scope type Scopedereferences to the context whileEarlyScopedoes not
Thats it. But in reality it’s important. For example, rotor-dns creates a pair: a state machine and a resolver object. State machine is just added to a loop, but you may want to put resolver object to a context. For example:
extern crate rotor_dns;
let resolver_opt = None;
try!(loop_creator.add_machine_with(|scope| {
let (res, fsm) = try!(rotor_dns::create_resolver(scope, cfg));
resolver_opt = Some(res);
Ok(fsm)
}));
let resolver = resolver_opt.unwrap();
let mut loop_instance = loop_creator.instantiate(Context {
dns: resolver,
});
loop_instance.add_machine_with(..)
With rotor-tools the code is simplified to:
extern crate rotor_dns;
extern crate rotor_tools;
use rotor_tools::LoopExt; // The trait with helper functions
let resolver = try!(loop_creator.add_and_fetch(|scope| {
rotor_dns::create_resolver(scope, cfg)
}));
let mut loop_instance = loop_creator.instantiate(Context {
dns: resolver,
});
loop_instance.add_machine_with(..)