Sonr is built on top of Mio with the aim to make it easier to create networking applications.
The two main components of Sonr are the Reactor
and the System
.
A Reactor
reacts to Event
s from the System
, or the output of another
reactor. This makes it possible (and intended) to chain two
reactors. Such a chain is in it self a Reactor
, and can be chained further.
|
|
Once the System
receives an Event
it is pushed down the chain(s) of
reactors until a reactor matching the event id reacts, returning a Reaction
that is passed to the next Reactor
in the chain.
System
is thread local and has to exist for each thread using Reactors
.
There can only be one instance of a System
per thread, and this instance is created by
calling System::init()
(calling init
twice in the same thread will panic).
Reactor
The reactor trait consists of two types and a method:
|
|
Reactor
trait.
Chain
To chain one reactor with another the Output
of the first has to be
the same type as the Input
of the second.
The following example shows the creation of a chain from two reactors.
|
|
Event
s there is no need for the
System
.
Since reactors in a chain will always push data forward and never return
anything other than Reaction::Continue
it is not possible to capture the
output from line 46: chain.react(Raction::Value(input));
here.
To print the result in the above example it would be possible to create a third
reactor that prints the given Input
, however rather than creating yet another reactor
the map
function of a reactor accepts a closure that is called if the reactor
returns Reaction::Value(val)
, with val
as an argument.
Map
Updating the previous example to use map
to print the output of
UppercaseString
:
|
|
The map
function takes a closure as an argument, where the argument for the
closure is the Output
of the reactor.
Since the output of UppercaseString
is a String
, the map
function is
called with a closure FnMut(UppercaseString::Output) -> T
.
This is a convenient way to change the output of a reactor.
The ReactiveTcpListener
outputs a tuple: (TcpStream, SocketAddr)
.
The map function could be used here if the SocketAddr
is not required:
|
|
stream
instead of the tuple, the Reactor Output is
changed to TcpStream
from (TcpStream, SocketAddress)
And
Another method available on a Reactor is and
.
This is useful to run more than one reactor in parallel.
Since the output of a tcp listener is a stream and a socket address, it would
not be possible to chain two tcp listeners together.
It is also not possible to call System::start
twice in the same thread.
To run two tcp listeners at the same time use and
:
|
|
This means a Reaction::Event(event)
from the System
will be sent to the
first listener and the second listener.
System
A Reactor
such as
ReactiveTcpListener
or a
ReactiveTcpStream
depend on
system events to notify them when they can read and/or write, or accept incoming
connections.
Therefore the System::init
call has to come before a ReactiveTcpStream
or a
ReactiveTcpListener
is created.
Once System::start(reactor)
is called, the System
polls Event
s and passes the events the reactor.
If the event does not belong to the reactor it is passed down the chain until a reactor reacts to the event.
The System
has a few responsibilities:
- Polling system events and passing them to the reactors
- Registering / Re registering
Evented
types - Managing tokens used when registering an
Evented
type
The System
also registers EventedReactors
Shutting down a System
Calling init
returns a SignalSender<SystemEvent>
.
At the time of writing the SystemEvent
only contains one variance: Stop
.
|
|