SlideShare a Scribd company logo
1 of 115
Download to read offline
Dive into SObjectizer-5.5
SObjectizer Team, Jan 2016
Eighth Part: Dispatchers
(at v.5.5.15)
This is the next part of the series of presentations with deep
introduction into features of SObjectizer-5.5.
This part is dedicated to dispatchers which are one of the
cornerstones of SObjectizer.
Dispatchers play a significant role in the behaviour of any
SObjectizer-based application.
Because of that understanding of dispatcher concept is
necessary for usage of SObjectizer framework.
SObjectizer Team, Jan 2016
What Is A Dispatcher?
SObjectizer Team, Jan 2016
Long story short:
Dispatchers manage event queues and provide
working threads on which agents handle their events.
If you don't understand what does it mean, don't worry.
There is a slightly longer explanation...
SObjectizer Team, Jan 2016
The main form of agents interaction in SObjectizer is
asynchronous message passing.
An agent sends a message to some mbox. If there is a
subscriber for that message type on that mbox then an event
is created. An event is an info about a specific message
which must be delivered to the specific agent.
Event are stored in events queue.
SObjectizer Team, Jan 2016
An event must be extracted from event queue and the
message from that event must be passed to agent-receiver
for processing.
Agent-receiver processes message by event handler which
is subscribed to this message type. Event handler is
represented by agent's method or just lambda-function.
Event handler is called on the context of some thread of
execution. This thread is provided by dispatcher.
SObjectizer Team, Jan 2016
Every working thread on the context of which an event
handler is invoked belongs to some dispatcher.
So a dispatcher can be seen as manager of working threads
to be used for invocation of event handlers.
Creation and deletion of working threads is an area of
responsibility of dispatcher.
SObjectizer Team, Jan 2016
There could be many dispatchers in SObjectizer
Environment. Each of them will have its own set of working
threads.
Every agent should be bound to some dispatcher. Binding is
done during registration of agent's coop. A programmer can
select a dispatcher for a specific agent.
Once agent is bound to a dispatcher all agent's events will
be handled on working threads of that dispatcher.
SObjectizer Team, Jan 2016
A dispatcher is not only a manager for working threads.
It also manages event queues for agents which are bound to
that dispatcher.
It is a significant difference of SObjectizer from other actor
frameworks: an event queue doesn't belong to an agent. A
queue is created and managed by dispatcher.
SObjectizer Team, Jan 2016
Another difference of SObjectizer from other actor
framework is a quantity of event queues.
In the "classical" actor-based approach every actor has its
own queue with messages to be processed.
In SObjectizer a dispatcher makes decision how many event
queues are necessary for serving agents bound to that
dispatcher.
SObjectizer Team, Jan 2016
The simplest dispatcher type in SObjectizer, one_thread
dispatcher, uses just one event queue for all agents bound
to that dispatcher.
Much more complex dispatchers like thread_pool and
adv_thread_pool can create as many event queues as it
required by a programmer.
Because of that every dispatcher has its own logic of
handling event queues and dispatching events for
processing by agents.
SObjectizer Team, Jan 2016
So now we can say that dispatcher is responsible for:
● creation and deletion of working threads;
● creation and deletion of event queues;
● extraction of events from event queues and invocation of
event-handlers on context of dispatcher's working
threads.
Different dispatchers do these action differently. So a user
can choose the most appropriate dispatcher for a particular
task.
SObjectizer Team, Jan 2016
Why Do We Need Dispatchers?
SObjectizer Team, Jan 2016
For what purpose does SObjectizer support different kinds of
dispatchers and allow to create several dispatchers in an
application?
Why a simple approach with one thread pool for all agents is
not used?
For what reasons a user should take care about dispatcher
and bind agents to some dispatcher?
SObjectizer Team, Jan 2016
It is a direct consequence of SObjectizer's primary target:
simplification of development of multithreading application.
SObjectizer doesn't hide threads from user.
But simplifies their usage and provides a way for safe
interaction between threads via asynchronous message
passing.
SObjectizer Team, Jan 2016
A user may require dedicated threads for performing long
and CPU-intensive calculations in background.
Or dedicated threads might be necessary for interaction with
some hardware attached to your computer.
Or dedicated threads might be needed to do blocking calls to
some 3rd party library.
Or thread pool can be necessary for efficient processing of
some event stream.
SObjectizer Team, Jan 2016
So there can be different reasons to use threads for solving
some real-world problems.
What we can do with that?
We can create and manage working threads manually. We
can pass information between threads via some ad-hoc
implementations of event queues or synchronize access to
shared data via low-level mechanisms like semaphores,
mutexes, condition variables and so on...
SObjectizer Team, Jan 2016
Or we can get a ready-to-use tools for management of
working threads and inter-thread message passing.
SObjectizer provides such tools:
● working thread management and events scheduling is
done via dispatchers;
● inter-thread message passing is implemented via general
message delivery mechanism (mboxes, event
subscriptions and so on).
SObjectizer Team, Jan 2016
And because different users require different thread
management policies there are different dispatchers in
SObjectizer.
And because of that there is a possibility to create any
number of dispatchers in an application.
All of that should allow to user to solve its domain-specific
task by most appropriate way.
SObjectizer Team, Jan 2016
But it doesn't mean that a user must take care about a
dispatcher for every agent.
A user can take care if he wants. But if not...
...there are such things as default dispatcher and coop's
main dispatcher binder which significantly simplify working
with SObjectizer.
SObjectizer Team, Jan 2016
An SObjectizer Environment has the default dispatcher. It is
created and started automatically.
The default dispatcher is an instance of one_thread
dispatcher. It means that all agents bound to that dispatcher
will work on the same working thread.
If a user doesn't specify a dispatcher for agent or agent's
coop then agent will be bound to the default dispatcher.
SObjectizer Team, Jan 2016
Dispatcher Binder
SObjectizer Team, Jan 2016
A binding of an agent to a dispatcher is done via separate
object called dispatcher binder.
Dispatcher binder knows how to bind agent to dispatcher
instance during agent registration. And how unbind the agent
during deregistration.
Every dispatcher implements its own dispatcher binder.
It means that if a user wants to bind agent to active_obj
dispatcher instance the user must create an active_obj
dispatcher binder.
SObjectizer Team, Jan 2016
Binder can be specified for an agent during agent creation:
auto coop = env.create_coop( so_5::autoname );
// An agent will be bound to one_thread dispatcher with name "Monitor".
coop->make_agent_with_binder< some_agent_type >(
// Creation of dispatcher binder.
so_5::disp::one_thread::create_disp_binder( "Monitor" ),
... /* Args for some_agent_type constructor */ );
// An agent will be bound to active_obj dispatcher witn name "Handler".
coop->make_agent_with_binder< some_agent_type >(
so_5::disp::active_obj::create_disp_binder( "Handler" ),
... );
SObjectizer Team, Jan 2016
Binder can also be specified for the whole coop. Such binder
will be main binder for that coop:
auto coop = env.create_coop( so_5::autoname,
// A main binder for coop will be a binder to active_obj dispatcher with the name "Handler".
so_5::disp::active_obj::create_disp_binder( "Handler" ) );
// This agent will be bound via coop's main binder to active_obj dispatcher with the name "Handler".
coop->make_agent< some_agent_type >( ... );
// This agent will also be bound to active_obj dispatcher with the name "Handler".
coop->make_agent< another_agent_type >( ... );
// But this agent will be bound to one_thread dispatcher with the name "Monitor". It is because
// a separate dispatcher binder is set for that agent.
coop->make_agent_with_binder< some_agent_type >(
so_5::disp::one_thread::create_disp_binder( "Monitor" ), ... );
SObjectizer Team, Jan 2016
If a dispatcher binder is not set for a coop then a binder for
the default dispatcher will be used as main binder for that
coop.
SObjectizer Team, Jan 2016
Public And Private Dispatchers
SObjectizer Team, Jan 2016
There are two kinds of dispatchers in SObjectizer: public and
private.
There are important differences in how to work with them.
SObjectizer Team, Jan 2016
Public dispatchers must have unique names. They are
accessed by means of their names.
Once created public dispatchers stay inside SObjectizer
Environment until Environment finished its work.
It means that an instance of public dispatcher will work even
when no one is using it.
SObjectizer Team, Jan 2016
Private dispatchers are accessible only via direct references
obtained during dispatchers creation.
Private dispatchers are destroyed automatically when no
one uses them.
SObjectizer Team, Jan 2016
A public dispatcher instance is passed to SObjectizer
Environment via environment_params_t object which could
be tuned in the launch() function:
so_5::launch( []( so_5::environment_t & ) { ... },
// Environment's parameters tuning lambda.
[]( so_5::environment_params_t & params ) {
// Addition of a public active_obj dispatcher with the name "Handler".
params.named_dispatcher( "Handler", so_5::disp::active_obj::create_disp() );
// Addition of a public one_thread dispatcher with the name "Monitor".
params.named_dispatcher( "Monitor", so_5::disp::one_thread::create_disp() );
} );
SObjectizer Team, Jan 2016
Another way of creation of a public dispatcher instance is the
usage of add_dispatcher_if_not_exists method:
void my_agent::evt_long_request( const request & evt )
{
// New child cooperation is necessary for handling the request.
// An instance of dispatcher is required for the cooperation.
// Create a dispatcher if it doesn't exist.
so_environment().add_dispatcher_if_not_exists(
"request_handler", [] { return so_5::disp::active_group::create_disp(); } );
so_5::introduce_child_coop( *this,
so_5::disp::active_group::create_disp_binder( "request_handler" ),
[&]( so_5::coop_t & coop ) {
...
} );
}
SObjectizer Team, Jan 2016
A binder for public dispatcher is created via appropriate
create_disp_binder() function which receives the name of
the dispatcher:
auto coop = env.create_coop( so_5::autoname,
// A main binder for coop will be a binder to active_obj dispatcher with name "Handler".
so_5::disp::active_obj::create_disp_binder( "Handler" ) );
...
// This agent will be bound to one_thread dispatcher with name "Monitor". It is because
// a personal dispatcher binder is set for that agent.
coop->make_agent_with_binder< some_agent_type >(
so_5::disp::one_thread::create_disp_binder( "Monitor" ), ... );
SObjectizer Team, Jan 2016
An instance of private dispatcher is created by appropriate
create_private_disp() which is implemented for every
standard dispatcher type in SObjectizer.
A kind of smart pointer is returned by create_private_disp()
function. This handle can be used for binding agents for that
private dispatcher instance.
The instance will be destroyed automatically when no one
uses this handle anymore.
SObjectizer Team, Jan 2016
An example of creating private dispatchers:
auto coop = env.create_coop( so_5::autoname,
// A main binder for coop will be a binder to a private active_obj dispatcher.
so_5::disp::active_obj::create_private_disp( env )->binder() );
// This agent will be bound via coop's main binder to active_obj dispatcher.
coop->make_agent< some_agent_type >( ... );
// This agent will also be bound to active_obj dispatcher.
coop->make_agent< another_agent_type >( ... );
// But this agent will be bound to private one_thread dispatcher.
coop->make_agent_with_binder< some_agent_type >(
so_5::disp::one_thread::create_private_disp( env )->binder(), ... );
SObjectizer Team, Jan 2016
Public dispatchers were created in the very first versions of
SObjectizer and they have some limitations. For example
there is no way to stop a public dispatcher if no one uses it.
Private dispatchers were added later and they solve some
problems related to public dispatchers.
Because of that usage of private dispatchers is preferable.
SObjectizer Team, Jan 2016
Event Handler Thread Safety
SObjectizer Team, Jan 2016
All event handlers are treated as not thread safe by default.
It means that if there are events E1 and E2 in event queue
for some agent A then these events will be delivered to A
one after another.
It is impossible that event handler for E1 is running at the
same time as event handler for E2 but on different thread.
SObjectizer guarantees that one event handler completed its
execution and only then the next event handler will be called.
SObjectizer Team, Jan 2016
Thread safety has sense on dispatchers which use pools of
threads.
Such dispatchers can migrate an agent from one working
thread to another.
Because such migration can take place the SObjectizer's
thread safety guarantee simplifies development of agents:
there is no need for synchronization of access to agent's
internals by using locks or something like that.
SObjectizer Team, Jan 2016
User can mark an event handler as thread safe.
For example if event handler doesn't modify state of the
agent. Or if such modification is implemented via usage of
appropriate mechanism like mutex or spinlock.
Most of standard SObjectizer's dispatchers will ignore that
mark and will treat every event handler as thread unsafe.
But there is adv_thread_pool dispatcher which can use that
mark appropriately.
SObjectizer Team, Jan 2016
When agent is bound to adv_thread_pool dispatcher and
event handler H is marked as thread safe then the
dispatcher can schedule calls of H for different events on
several of working threads at the same time.
Moreover if agent has thread safe event handler H and not
thread safe event handler G then adv_thread_pool will
guarantee that all event handlers H will finish its work before
a single event handler G will be invoked.
SObjectizer Team, Jan 2016
At v.5.5.15 there is only one dispatcher which can
distinguish between not thread safe and thread safe event
handlers.
But more dispatchers with such abilities can be introduced in
the future versions of SObjectizer.
SObjectizer Team, Jan 2016
A Brief Overview Of Existing Dispatchers
SObjectizer Team, Jan 2016
There are eight standard dispatchers in SObjectizer-5.5
Five of them do not support agent's priorities: one_thread,
active_obj, active_group, thread_pool and adv_thread_pool.
These dispatcher think that all agents have the same priority.
Three dispatchers support agent's priorities:
prio_one_thread::strictly_ordered, prio_one_thread::
quoted_round_robin, prio_dedicated_threads::one_per_prio.
They schedule agents with respect to agent's priority.
SObjectizer Team, Jan 2016
All stuff related to some dispatcher is defined in a specific
namespace inside so_5::disp.
For example:
so_5::disp::active_obj
so_5::disp::thread_pool
so_5::disp::prio_one_thread::strictly_ordered
SObjectizer Team, Jan 2016
Every dispatcher-specific namespace has the similar set of
functions and classes like:
create_disp, create_private_disp, create_disp_binder
queue_params_t, disp_params_t, bind_params_t
This makes usage of different dispatchers very similar: if you
know how to create one_thread dispatcher you easily create
create active_obj or thread_pool dispatcher.
SObjectizer Team, Jan 2016
one_thread Dispatcher
SObjectizer Team, Jan 2016
one_thread dispatcher is the oldest, simplest and,
sometimes, most useful dispatcher.
It creates just one working thread and just one event queue.
Events for all agents bound to that dispatcher are stored in
single event queue.
The single working thread gets the next event from the
queue and runs event handler form agent-receiver. Then
gets the next event and so on.
SObjectizer Team, Jan 2016
It is possible to say that one_thread implements cooperative
multitasking: if some agent hangs then all other agents
bound to that dispatcher will hang too.
SObjectizer Team, Jan 2016
active_obj Dispatcher
SObjectizer Team, Jan 2016
active_obj is another very old and simple dispatcher.
But now, after addition of private dispatchers to SObjectizer,
it is less useful than before.
active_obj dispatcher creates a separate working thread and
separate event queue for every agent bound to that
dispatcher.
It means that every agent will have its own working thread
and its own event queue.
SObjectizer Team, Jan 2016
active_obj dispatcher creates a new event queue and
launches a new working thread for every agent bound to it.
When agent is deregistered the dispatcher stops the working
thread of this agent and deletes the corresponding event
queue.
It means that if there are no agents bound to active_obj
dispatcher there are no working threads nor event queues.
SObjectizer Team, Jan 2016
active_obj dispatcher is useful if it is necessary to provide a
separate working thread for some agent.
For example if agent needs a dedicated context for long-
running activities like interaction with hardware devices,
performing blocking calls to 3rd party libraries or external
systems and so on.
The similar effect can be achieved by using a private
one_thread dispatcher. But sometimes usage of active_obj
dispatcher requires less efforts...
SObjectizer Team, Jan 2016
An example of usage of active_obj dispatcher:
auto coop = env.create_coop( so_5::autoname,
// A main binder for coop will be binder to private active_obj dispatcher.
// It means that all agents of the coop without explicitly specified
// binder will be bound to that active_obj dispatcher and become
// active objects with own working thread.
so_5::disp::active_obj::create_private_disp( env )->binder() );
for( const auto & d : devices )
// Create a separate agent for every device.
coop->make_agent< device_manager >( d );
env.register_coop( std::move(coop) );
SObjectizer Team, Jan 2016
active_group Dispatcher
SObjectizer Team, Jan 2016
active_group is another very old and simple dispatcher.
But now, after addition of private dispatchers to SObjectizer,
it is less useful than before and can be replaced by private
one_thread dispatcher.
active_group dispatcher creates a separate working thread
and separate event queue for named group of agents. It
means that all agents from the same group will work on a
common working thread.
SObjectizer Team, Jan 2016
active_group dispatcher creates a new working thread and a
new event queue when the first agent of new group is
registered.
active_group dispatcher stops group's working thread and
destroy group's event queue when the last agent from the
group is deregistered. It means that all resources for a group
are deallocated when group lost the last member.
SObjectizer Team, Jan 2016
If a new agent is added to group which disappear earlier a
new group with the same name will be created.
For example:
● agents A and B is being registered as part of group G1;
● new group G1 is created, new working thread is started for G1;
● agents A and B are deregistered;
● working thread for G1 is stopped, group G1 is deleted;
● agents C and D is being registered as part of group G1;
● new group G1 is created, new working thread is started for G1;
SObjectizer Team, Jan 2016
Every instance of active_group dispatcher has its own set of
active groups.
A group name must be unique only inside one dispatcher
instance. It means that dispatcher instance ag1 can have
group G1 and dispatcher instance ag2 can have group G1
too.
These groups will be different. Lifetime of ag1.G1 and ag2.
G1 will be independent from each other.
SObjectizer Team, Jan 2016
active_group dispatcher can be useful if it is necessary to
bind a group of agents to the same working thread. For
example if these agents performs different stages of
complex requests processing.
Let's imagine a processing pipeline of three stages: requests
params validation, request processing and generation of
results. Every of these states can take a long time so it is
better to provide a separate context to every request.
It can be done by using active_group dispatcher...
SObjectizer Team, Jan 2016
An example of binding agents to the same active group:
std::string request_id = generate_request_id( request );
// Create coop with request ID used as coop name.
auto coop = env.create_coop( request_id,
// All agents of this coop will be part of active group on
// active_group dispatcher with name "Handlers".
// request_id will be used as group name.
so_5::disp::active_group::create_disp_binder( "Handlers", request_id ) );
// Filling coop with agents.
coop->make_agent< request_checker >( request );
coop->make_agent< request_handler >( request );
coop->make_agent< response_generator >( request );
env.register_coop( std::move(coop) );
SObjectizer Team, Jan 2016
After addition of private dispatcher to SObjectizer
active_group dispatcher can often be replaced by private
one_thread dispatcher.
But sometimes active_group dispatchers can still be useful.
For example if agents for request processing cannot be
created at the same time and agent for the next stage can
be registered only after completion of the previous state...
SObjectizer Team, Jan 2016
An example of addition of agents from different coops to the
same active group:
void request_acceptor::new_request( const request_type & request ) {
// A cooperation with the first stage must be created.
std::string request_id = generate_request_id( request );
env.introduce_coop( request_id + "-checker",
so_5::disp::active_group::create_disp_binder( "Handlers", request_id ),
[&]( so_5::coop_t & coop ) { coop.make_agent< request_checker >( request ); } );
}
...
void request_checker::check_completed() {
// A cooperation with the second stage can be created.
std::string request_id = generate_request_id( request );
so_environment().introduce_coop( request_id + "-handler",
so_5::disp::active_group::create_disp_binder( "Handlers", request_id ),
[&]( so_5::coop_t & coop ) { coop.make_agent< request_handler >( request ); } );
}
SObjectizer Team, Jan 2016
thread_pool Dispatcher
SObjectizer Team, Jan 2016
thread_pool dispatcher creates a pool with several working
threads.
An agent bound to thread_pool dispatcher can handle its
events on any of working threads from that pool.
thread_pool dispatcher guarantees that at any given moment
only single event handler of the agent might run thus using
only one of the working threads. It is impossible to run event
handlers e1 and e2 of agent A on different thread at the
same time.
SObjectizer Team, Jan 2016
The most complicated moment in thread_pool dispatcher is
event queues.
There are two important things which need to be mentioned
for understanding of thread_pool dispatcher logic:
● type of FIFO for agent/coop;
● max_demands_at_once parameter.
SObjectizer Team, Jan 2016
Type of FIFO determines the relationship between event
handlers of agents from one coop.
Suppose there is a coop with agents A, B and C. Some
agent D sends the following messages in exactly that order:
● M1 to A
● M2 to B
● M3 to A
● M4 to C
● M5 to B
SObjectizer Team, Jan 2016
If agents A, B and C use cooperation FIFO then all these
agents will use one common event queue. Sequence of
event handler calls will look like:
1. A's event handler for M1
2. B's event handler for M2
3. A's event handler for M3
4. C's event handler for M4
5. B's event handler for M5
Exactly in that order. B's event handler for M2 will be called only
when A's event handler for M1 finished its work.
SObjectizer Team, Jan 2016
Cooperation FIFO also means that agents with that FIFO
type cannot work on different threads at the same time.
For example it is possible that agent A will handle M1 on
thread T1. Then agent B will handle M2 on thread T2. Then
agent A will handle M3 on T3.
But it is impossible that A will handle M1 on T1 and B will
handle M2 on T2 at the same time.
SObjectizer Team, Jan 2016
If agents A, B and C use individual FIFO then all these
agents will use different and independent event queues. It is
hard to predict as a sequence of event handlers will look like.
For example:
1. A's event handler for M1 on thread T1
2. B's event handler for M2 on thread T2
3. C's event handler for M4 on thread T3
4. B's event handler for M5 on thread T2
5. A's event handler for M3 on thread T1
SObjectizer Team, Jan 2016
Individual FIFO also means that agents with that FIFO type
can work on different threads in parallel.
For example it is possible that agent A will handle M1 on
thread T1. At the same time agent B will handle M2 on
thread T2. At the same time agent C will handle M4 on
thread T3.
SObjectizer Team, Jan 2016
There is another side of FIFO type: thread safety.
If agents from a coop use cooperative FIFO then they do not
need to synchronize access to some shared data.
Suppose several agents from one coop use common std::map
object. Because these agents cannot work on different threads
at the same time they can read and modify that object without
any mutexes or something like that.
But if agents use individual FIFO every shared data must be
protected or completely avoided.
SObjectizer Team, Jan 2016
Parameter max_demands_at_once tells how many events
from an event queue can be processed by working thread
before switching to processing of another event queue.
This parameter is important because every working thread in
thread_pool dispatcher works this way:
● gets the next non-empty event queue;
● handle at most max_demands_at_once events from it;
● gets the next non-empty event queue;
● ...
SObjectizer Team, Jan 2016
Suppose there are agents A, B and C from one coop with
cooperation FIFO and events for messages M1, M2, ..., M5
in their event queue....
SObjectizer Team, Jan 2016
If max_demands_at_once is 4 then the following scenario
might happen:
● some working thread T1 gets this event queue and calls
event handlers for messages M1, ..., M4;
● working thread T1 switches for handling different event
queue. Event queue for A, B, C agents holds M5;
● some working thread Tn gets this event queue and calls
event handler for M5;
● event queue for A, B, C agents becomes empty and Tn
switches to another event queue.
SObjectizer Team, Jan 2016
If max_demands_at_once is 1 then a working thread will
handle just one event from A, B, C agent queue.
Then this queue can be handled by another working thread
which will handle just one event.
Then this queue can be handled by another working thread...
And so on.
SObjectizer Team, Jan 2016
A more interesting situation can be if agents A, B and C use
individual FIFO.
In that case there will be independent queues for these
agents:
● a queue for A with M1 and M3;
● a queue for B with M2 and M5;
● a queue for C with M4.
SObjectizer Team, Jan 2016
If max_demands_at_once is greater than 1 then there could
be the following scenario:
● thread T1 handles M1 and M3 for A;
● thread T2 handles M4 for C;
● thread T3 handles M2 and M5 for B.
But if there are just two working threads in the pool:
● thread T1 handles M1 and M3 for A;
● thread T2 handles M4 for C;
● thread T1 handles M2 and M5 for B.
SObjectizer Team, Jan 2016
Value of max_demands_at_once determines how often a
working thread will switch from one event queue to another.
It can have a huge impact on application performance: small
values of max_demands_at_once will lead to frequent queue
switching and this will slow down event processing.
So large values of max_demands_at_once can speed up
event processing if there is a dense flow of events.
SObjectizer Team, Jan 2016
Implementation of thread_pool dispatcher makes things yet
more complex and interesting: every agent for a coop can
have its own parameters for thread_pool dispatcher.
It means that agent A can have individual FIFO and
max_demands_at_once=100, but agents B and C from the
same coop will have cooperation FIFO and
max_demands_at_once=10.
In this case two different event queues will be created: one
for A and another for B and C.
SObjectizer Team, Jan 2016
This complex logic of thread_pool allows precise
performance tuning for complex use cases which can be
found in real-life problems.
But in the simple cases the default parameters can be used
(cooperation FIFO and max_demands_at_once=4). This
significantly simplifies usage of thread_pool dispatcher.
Especially when several coops are bound to the same
thread_pool dispatcher instance.
SObjectizer Team, Jan 2016
An example for thread_pool dispatcher:
void init( so_5::environment_t & env )
{
using namespace so_5::disp::thread_pool;
env.introduce_coop(
// Create an instance of thread_pool dispatcher with 3 working threads.
create_private_disp( env, 3 )->binder(
// All agents will use individual FIFO.
// Parameter max_demands_at_once will have the default value.
bind_params_t{}.fifo( fifo_t::individual ) ),
[]( so_5::coop_t & c ) {
auto collector = c.make_agent< a_collector_t >();
auto performer = c.make_agent< a_performer_t >( collector->so_direct_mbox() );
collector->set_performer_mbox( performer->so_direct_mbox() );
c.make_agent< a_generator_t >( collector->so_direct_mbox() );
});
}
SObjectizer Team, Jan 2016
adv_thread_pool Dispatcher
SObjectizer Team, Jan 2016
adv_thread_pool dispatcher is similar to thread_pool
dispatcher but has two important differences:
1. It allows to invoke several thread safe event handlers for
an agent at the same time on different threads.
2. As a consequence of previous point there is no
max_demands_at_once parameter.
SObjectizer Team, Jan 2016
Every working thread in adv_thread_pool works this way:
● gets some non-empty event queue;
● gets the first event from that queue;
● checks thread safety for event handler for that event;
● checks a possibility of invocation of this event handler;
● if event handler can be invoked it is called;
● if event handler cannot be invoked then event is returned
to event queue and thread switches to another non-
empty event queue.
SObjectizer Team, Jan 2016
An event handler for an agent can be called if:
● it is not thread safe and there is no any other event
handlers of that agent which are running now on one of the
threads;
● or it is thread safe and there is no any not thread safe event
handler which is working now on some thread.
It means that only one not thread safe event handler can be
called. And next event handler can be called only after
completion of previous handler. Several thread safe handlers
can work at the same time.
SObjectizer Team, Jan 2016
There are two types of FIFO for adv_thread_pool:
cooperation and individual. Just like in thread_pool
dispatcher.
But in adv_thread_pool FIFO type has influence on checking
for thread safety of event handler.
Suppose there are agents A and B from one coop and they
use cooperation FIFO. Suppose also that event handlers A.
e1 and B.e2 are thread safe, but event handler A.e3 is not.
SObjectizer Team, Jan 2016
If there is events e1, e2, e3, e2, e1, e3 in the event queue
for A and B agents then event handlers will be called in the
following sequence: A.e1 on thread T1, B.e2 on thread T2.
Only after completion of event handlers A.e1 and B.e2 event
handler A.e3 will be called.
Then A.e1 on T1 and B.e2 on T2. Then waiting for
completion and the call to A.e3.
SObjectizer Team, Jan 2016
If agents A and B use individual FIFO and there are events
sequence {e1, e3, e1} and {e2, e2} in two event queues then
there could be the following scenario:
● A.e1 on T1, then A.e3 on T1, then A.e1 on T1;
● B.e2 on T2;
● B.e2 on T3.
SObjectizer Team, Jan 2016
adv_thread_pool can be useful for spreading thread safe
event processing on several working threads.
For example there could be cryptographer agent which performs
make_signature, check_signature, encrypt_block and
decrypt_block operations.
These operations are thread safe because they don't change the
state of cryptographer agent. Event handler for these operations
can be marked as thread safe. This allows to handle several
cryptographic operations at the same time in parallel.
SObjectizer Team, Jan 2016
Subscription of thread safe event handler:
class cryptographer : public so_5::agent_t
{
void on_make_signature( const make_signature & ) {...}
void on_check_signature( const check_signature & ) {...}
void on_encrypt_block( const encrypt_block & ) {...}
void on_decrypt_block( const decrypt_block & ) {...}
...
virtual void so_define_agent() override {
so_subscribe_self()
.event( &cryptographer::on_make_signature, so_5::thread_safe )
.event( &cryptographer::on_check_signature, so_5::thread_safe )
.event( &cryptographer::on_encrypt_block, so_5::thread_safe )
.event( &cryptographer::on_decrypt_block, so_5::thread_safe )
...
}
}
SObjectizer Team, Jan 2016
An agent can have thread safe and not thread safe event
handlers.
For example cryptographer agent can have not thread safe
event handler for message reconfigure.
In this case adv_thread_pool dispatcher guarantees that all
thread safe event handlers finish their work before an event
handler for reconfigure message will be started.
SObjectizer Team, Jan 2016
An example of binding agent to adv_thread_pool dispatcher:
using namespace so_5::disp::adv_thread_pool;
env.introduce_coop(
// All agents of new coop will work on adv_thread_pool dispatcher.
// Every agent will use individual FIFO.
create_private_disp( env, 4 )->binder( bind_params_t{}.fifo( fifo_t::individual ) ),
[]( so_5::coop_t & coop ) {
coop.make_agent< cryptographer >();
...
} );
SObjectizer Team, Jan 2016
prio_one_thread::strictly_ordered Dispatcher
SObjectizer Team, Jan 2016
prio_one_thread::strictly_ordered dispatcher allows for
events of high priority agents to block events of low priority
agents.
It means that events queue is always strictly ordered: events
for agents with high priority are placed before events for
agents with lower priority.
SObjectizer Team, Jan 2016
For example if event queue is {e1(a7), e2(a6), e3(a4), e4
(a4)}, where a7 means an agent with priority p7, then events
will be handled in exact that order.
After handling e1 the queue will be {e2(a6), e3(a4), e4(a4)}.
If e5 for a5 arrived then the queue will become {e2(a6), e5
(a5), e3(a4), e4(a4)}.
It means that chronological order of events will be preserved
only for events of agents with the same priority.
SObjectizer Team, Jan 2016
This dispatcher could be useful if there is a necessity of
handling some messages before other messages.
For example there could be a stream of tasks represented
by take_job messages. There also could be a special
message for task processor’s reconfiguration: new_config
message.
It could have a sense to handle new_config as soon as
possible.
SObjectizer Team, Jan 2016
This can be done by two agents which are bound to single
prio_one_thread::strictly_ordered dispatcher.
One agent will have priority p1 and will handle new_config
message. Second agent will have priority p0 and will handle
take_job.
Both agents will have common shared data (at least
configuration parameters, may be something else). Dispatcher
prio_one_thread::strictly_ordered guarantees that new_config
will be handled as soon as processing of previous message
finished.
SObjectizer Team, Jan 2016
An example of binding agents to prio_one_thread::
strictly_ordered dispatcher:
namespace prio_disp = so_5::disp::prio_one_thread::strictly_ordered;
env.introduce_coop(
// Dispatcher instance and binder for it.
prio_disp::create_private_disp( env )->binder(),
[]( so_5::coop_t & coop ) {
// An agent with higher priority.
coop.make_agent< config_manager >( so_5::prio::p1 );
// An agent with lower priority.
coop.make_agent< job_performer >( so_5::prio::p0 );
} );
SObjectizer Team, Jan 2016
prio_one_thread::quoted_round_robin Dispatcher
SObjectizer Team, Jan 2016
prio_one_thread::quoted_round_robin dispatcher works on
round-robin principle.
It allows to specify maximum count of events to be
processed consequently for the specified priority. After
processing that count of events dispatcher switches to
processing events of lower priority even if there are yet more
events of higher priority to be processed.
SObjectizer Team, Jan 2016
Dispatcher handles no more than Q7 events of priority p7,
then no more than Q6 events of priority p6, ..., then no more
than Q0 events of priority p0.
If an event of higher priority is arrived during handling a
quote for lower priority no switching is performed.
For example if dispatcher handles events of priority p5 and
event of priority p7 is arrived the dispatcher will continue to
handle events of p5, then events of p4 (if any), ..., then
events of p0 (if any). And only then events of p7.
SObjectizer Team, Jan 2016
This working scheme means that agent’s priorities treated as
agent’s weight.
A programmer can set bigger quotes for more prioritized
(more heavyweight) agents and that agents will receive more
resources than less prioritized (less weighted) agents.
SObjectizer Team, Jan 2016
A very important detail: events of the same priority are
handled in chronological order.
SObjectizer Team, Jan 2016
A dispatcher of that type can be useful, for example, if there
are agents which handles clients of different types.
Some clients are VIP clients and they should receive first-class
quality of service and there could be other clients with lower
demands for service quality.
A high priority to agents for handling VIP-client requests can be
used and a large quote for that priority can be set. All other agents
will have lower priority and smaller quote. As result more requests
from VIP-clients will be handled but there also will be processing
of request from other clients.
SObjectizer Team, Jan 2016
An example of binding agents to prio_one_thread::
quoted_round_robin dispatcher:
namespace prio_disp = so_5::disp::prio_one_thread::quoted_round_robin;
env.introduce_coop(
// Create dispatcher and define quotes for several priorities.
prio_disp::create_private_disp( env,
// By default every priority will have quote for 20 events.
prio_disp::quotes_t{ 20 }
// Priority p7 will have different quote.
.set( so_5::prio::p7, 45 )
// Priority p6 will have different quote too.
.set( so_5::prio::p6, 35 ) )->binder(),
[]( so_5::coop_t & coop ) {
coop.make_agent< vip_client_processor >( so_5::prio::p7 );
coop.make_agent< ordinal_client_processor >( so_5::prio::p6 );
coop.make_agent< free_client_processor >( so_5::prio::p0 );
} );
SObjectizer Team, Jan 2016
prio_dedicated_threads::one_per_prio Dispatcher
SObjectizer Team, Jan 2016
prio_dedicated_threads::one_per_prio dispatcher creates a
single dedicated thread for every priority.
It means that events for agents with priority p7 will be
handled on different thread than events for agents with, for
example, priority p6.
Events of the same priority are handled in chronological
order.
SObjectizer Team, Jan 2016
Because of the fact that priority is assigned to an agent at its
creation and cannot be changed later an agent inside
prio_dedicated_threads::one_per_prio is bound to a
particular working thread and do not moved from that thread
to any other thread.
This property of the dispatcher can be used for binding
processing of different message types to different working
threads: messages of type M1 can be processed by agent
A1 with priority p1, messages of type M2 -- by agent A2 with
priority p2 and so on...
SObjectizer Team, Jan 2016
Assigning different priorities for agents which handle
different message type may have sense if OS-specific API
for changing thread priority is used.
For example an agent with priority p7 can set higher priority
for its working thread in so_evt_start() method than agent
with priority p6.
SObjectizer Team, Jan 2016
An example of binding agents to prio_dedicated_threads::
one_per_prio dispatcher:
namespace prio_disp = so_5::disp::prio_dedicated_threads::one_per_prio;
env.introduce_coop(
// An instance of dispatcher and a binder for it.
prio_disp::create_private_disp( env )->binder(),
[]( so_5::coop_t & coop ) {
coop.make_agent< m1_handler >( so_5::prio::p1 );
coop.make_agent< m2_handler >( so_5::prio::p2 );
...
} );
SObjectizer Team, Jan 2016
Some Final Words
SObjectizer Team, Jan 2016
Dispatchers play significant role in application development
on top on SObjectizer-5.
It is because SObjectizer do not hide multithreading from a
user. But simplifies a work with multithreading in application
domains where threads are important.
Application domains are different. Even inside one domain
different event scheduling policies might be needed. This is
why SObjectizer provides several dispatcher types.
SObjectizer Team, Jan 2016
This presentation has no intention to be a comprehensive
guide for SObjectizer's dispatcher.
It is just an attempt to explain a role of dispatchers and a
short overview of standard SObjectizer's dispatcher and their
features.
For more detailed information please see corresponding
sections in the Project's Wiki and materials in the Project's
Blog.
SObjectizer Team, Jan 2016
Additional Information:
Project’s home: http://sourceforge.net/projects/sobjectizer
Documentation: http://sourceforge.net/p/sobjectizer/wiki/
Forum: http://sourceforge.net/p/sobjectizer/discussion/
Google-group: https://groups.google.com/forum/#!forum/sobjectizer
GitHub mirror: https://github.com/masterspline/SObjectizer

More Related Content

What's hot

Dive into SObjectizer 5.5. Ninth Part: Message Chains
Dive into SObjectizer 5.5. Ninth Part: Message ChainsDive into SObjectizer 5.5. Ninth Part: Message Chains
Dive into SObjectizer 5.5. Ninth Part: Message ChainsYauheni Akhotnikau
 
arataga. SObjectizer and RESTinio in action: a real-world example
arataga. SObjectizer and RESTinio in action: a real-world examplearataga. SObjectizer and RESTinio in action: a real-world example
arataga. SObjectizer and RESTinio in action: a real-world exampleYauheni Akhotnikau
 
2. Design patterns. part #2
2. Design patterns. part #22. Design patterns. part #2
2. Design patterns. part #2Leonid Maslov
 
Dependency Injection for Android @ Ciklum speakers corner Kiev 29. May 2014
Dependency Injection for Android @ Ciklum speakers corner Kiev 29. May 2014Dependency Injection for Android @ Ciklum speakers corner Kiev 29. May 2014
Dependency Injection for Android @ Ciklum speakers corner Kiev 29. May 2014First Tuesday Bergen
 
Testing RESTful Webservices using the REST-assured framework
Testing RESTful Webservices using the REST-assured frameworkTesting RESTful Webservices using the REST-assured framework
Testing RESTful Webservices using the REST-assured frameworkMicha Kops
 
Inversion of Control and Dependency Injection
Inversion of Control and Dependency InjectionInversion of Control and Dependency Injection
Inversion of Control and Dependency InjectionDinesh Sharma
 
Mvc interview questions – deep dive jinal desai
Mvc interview questions – deep dive   jinal desaiMvc interview questions – deep dive   jinal desai
Mvc interview questions – deep dive jinal desaijinaldesailive
 
Parallel Programming With Dot Net
Parallel Programming With Dot NetParallel Programming With Dot Net
Parallel Programming With Dot NetNeeraj Kaushik
 
Analysis of bugs in Orchard CMS
Analysis of bugs in Orchard CMSAnalysis of bugs in Orchard CMS
Analysis of bugs in Orchard CMSPVS-Studio
 
Creating a Java EE 7 Websocket Chat Application
Creating a Java EE 7 Websocket Chat ApplicationCreating a Java EE 7 Websocket Chat Application
Creating a Java EE 7 Websocket Chat ApplicationMicha Kops
 
"Node.js threads for I/O-bound tasks", Timur Shemsedinov
"Node.js threads for I/O-bound tasks", Timur Shemsedinov"Node.js threads for I/O-bound tasks", Timur Shemsedinov
"Node.js threads for I/O-bound tasks", Timur ShemsedinovFwdays
 
Understanding react hooks
Understanding react hooksUnderstanding react hooks
Understanding react hooksSamundra khatri
 
Keeping track of state in asynchronous callbacks
Keeping track of state in asynchronous callbacksKeeping track of state in asynchronous callbacks
Keeping track of state in asynchronous callbacksPaul Houle
 

What's hot (20)

Dive into SObjectizer 5.5. Ninth Part: Message Chains
Dive into SObjectizer 5.5. Ninth Part: Message ChainsDive into SObjectizer 5.5. Ninth Part: Message Chains
Dive into SObjectizer 5.5. Ninth Part: Message Chains
 
arataga. SObjectizer and RESTinio in action: a real-world example
arataga. SObjectizer and RESTinio in action: a real-world examplearataga. SObjectizer and RESTinio in action: a real-world example
arataga. SObjectizer and RESTinio in action: a real-world example
 
2. Design patterns. part #2
2. Design patterns. part #22. Design patterns. part #2
2. Design patterns. part #2
 
Bot builder v4 HOL
Bot builder v4 HOLBot builder v4 HOL
Bot builder v4 HOL
 
ajax_pdf
ajax_pdfajax_pdf
ajax_pdf
 
Dependency Injection for Android
Dependency Injection for AndroidDependency Injection for Android
Dependency Injection for Android
 
Dependency Injection for Android @ Ciklum speakers corner Kiev 29. May 2014
Dependency Injection for Android @ Ciklum speakers corner Kiev 29. May 2014Dependency Injection for Android @ Ciklum speakers corner Kiev 29. May 2014
Dependency Injection for Android @ Ciklum speakers corner Kiev 29. May 2014
 
Testing RESTful Webservices using the REST-assured framework
Testing RESTful Webservices using the REST-assured frameworkTesting RESTful Webservices using the REST-assured framework
Testing RESTful Webservices using the REST-assured framework
 
G pars
G parsG pars
G pars
 
Inversion of Control and Dependency Injection
Inversion of Control and Dependency InjectionInversion of Control and Dependency Injection
Inversion of Control and Dependency Injection
 
Mvc interview questions – deep dive jinal desai
Mvc interview questions – deep dive   jinal desaiMvc interview questions – deep dive   jinal desai
Mvc interview questions – deep dive jinal desai
 
Parallel Programming With Dot Net
Parallel Programming With Dot NetParallel Programming With Dot Net
Parallel Programming With Dot Net
 
Analysis of bugs in Orchard CMS
Analysis of bugs in Orchard CMSAnalysis of bugs in Orchard CMS
Analysis of bugs in Orchard CMS
 
Creating a Java EE 7 Websocket Chat Application
Creating a Java EE 7 Websocket Chat ApplicationCreating a Java EE 7 Websocket Chat Application
Creating a Java EE 7 Websocket Chat Application
 
JavaScript
JavaScriptJavaScript
JavaScript
 
my accadanic project ppt
my accadanic project pptmy accadanic project ppt
my accadanic project ppt
 
"Node.js threads for I/O-bound tasks", Timur Shemsedinov
"Node.js threads for I/O-bound tasks", Timur Shemsedinov"Node.js threads for I/O-bound tasks", Timur Shemsedinov
"Node.js threads for I/O-bound tasks", Timur Shemsedinov
 
Spring AOP
Spring AOPSpring AOP
Spring AOP
 
Understanding react hooks
Understanding react hooksUnderstanding react hooks
Understanding react hooks
 
Keeping track of state in asynchronous callbacks
Keeping track of state in asynchronous callbacksKeeping track of state in asynchronous callbacks
Keeping track of state in asynchronous callbacks
 

Viewers also liked

What’s new in SObjectizer 5.5.8
What’s new in SObjectizer 5.5.8What’s new in SObjectizer 5.5.8
What’s new in SObjectizer 5.5.8Yauheni Akhotnikau
 
2016-06 Malaysia Car Sales Mazda June 2016
2016-06 Malaysia Car Sales Mazda June 20162016-06 Malaysia Car Sales Mazda June 2016
2016-06 Malaysia Car Sales Mazda June 2016Uli Kaiser
 
Thailand Car Sales January-December 2014 Suzuki
Thailand Car Sales January-December 2014 SuzukiThailand Car Sales January-December 2014 Suzuki
Thailand Car Sales January-December 2014 SuzukiUli Kaiser
 
Thailand Automotive Sales Statistics by PPV Segment January 2016
Thailand Automotive Sales Statistics by PPV Segment January 2016Thailand Automotive Sales Statistics by PPV Segment January 2016
Thailand Automotive Sales Statistics by PPV Segment January 2016Uli Kaiser
 
Malaysia Domestic Vehicle Sales by Segment February 2016
Malaysia Domestic Vehicle Sales by Segment February 2016Malaysia Domestic Vehicle Sales by Segment February 2016
Malaysia Domestic Vehicle Sales by Segment February 2016Uli Kaiser
 
Thailand Car Sales Statistics Pickup Trucks December 2015
Thailand Car Sales Statistics Pickup Trucks December 2015Thailand Car Sales Statistics Pickup Trucks December 2015
Thailand Car Sales Statistics Pickup Trucks December 2015Uli Kaiser
 
Demystifying Orchestration and Assurance Across SDN NFV CE2.0
Demystifying Orchestration and Assurance Across SDN NFV CE2.0Demystifying Orchestration and Assurance Across SDN NFV CE2.0
Demystifying Orchestration and Assurance Across SDN NFV CE2.0WebNMS
 
Spain AutoBook Preview
Spain AutoBook PreviewSpain AutoBook Preview
Spain AutoBook PreviewUli Kaiser
 
Summit 16: Optimizing OPNFV for Distributed NFV Applications
Summit 16: Optimizing OPNFV for Distributed NFV ApplicationsSummit 16: Optimizing OPNFV for Distributed NFV Applications
Summit 16: Optimizing OPNFV for Distributed NFV ApplicationsOPNFV
 
South Korea AutoBook Preview
South Korea AutoBook PreviewSouth Korea AutoBook Preview
South Korea AutoBook PreviewUli Kaiser
 
Italy AutoBook 2017 Preview
Italy AutoBook 2017 PreviewItaly AutoBook 2017 Preview
Italy AutoBook 2017 PreviewUli Kaiser
 
EV-AV AutoBook Preview
EV-AV AutoBook PreviewEV-AV AutoBook Preview
EV-AV AutoBook PreviewUli Kaiser
 

Viewers also liked (12)

What’s new in SObjectizer 5.5.8
What’s new in SObjectizer 5.5.8What’s new in SObjectizer 5.5.8
What’s new in SObjectizer 5.5.8
 
2016-06 Malaysia Car Sales Mazda June 2016
2016-06 Malaysia Car Sales Mazda June 20162016-06 Malaysia Car Sales Mazda June 2016
2016-06 Malaysia Car Sales Mazda June 2016
 
Thailand Car Sales January-December 2014 Suzuki
Thailand Car Sales January-December 2014 SuzukiThailand Car Sales January-December 2014 Suzuki
Thailand Car Sales January-December 2014 Suzuki
 
Thailand Automotive Sales Statistics by PPV Segment January 2016
Thailand Automotive Sales Statistics by PPV Segment January 2016Thailand Automotive Sales Statistics by PPV Segment January 2016
Thailand Automotive Sales Statistics by PPV Segment January 2016
 
Malaysia Domestic Vehicle Sales by Segment February 2016
Malaysia Domestic Vehicle Sales by Segment February 2016Malaysia Domestic Vehicle Sales by Segment February 2016
Malaysia Domestic Vehicle Sales by Segment February 2016
 
Thailand Car Sales Statistics Pickup Trucks December 2015
Thailand Car Sales Statistics Pickup Trucks December 2015Thailand Car Sales Statistics Pickup Trucks December 2015
Thailand Car Sales Statistics Pickup Trucks December 2015
 
Demystifying Orchestration and Assurance Across SDN NFV CE2.0
Demystifying Orchestration and Assurance Across SDN NFV CE2.0Demystifying Orchestration and Assurance Across SDN NFV CE2.0
Demystifying Orchestration and Assurance Across SDN NFV CE2.0
 
Spain AutoBook Preview
Spain AutoBook PreviewSpain AutoBook Preview
Spain AutoBook Preview
 
Summit 16: Optimizing OPNFV for Distributed NFV Applications
Summit 16: Optimizing OPNFV for Distributed NFV ApplicationsSummit 16: Optimizing OPNFV for Distributed NFV Applications
Summit 16: Optimizing OPNFV for Distributed NFV Applications
 
South Korea AutoBook Preview
South Korea AutoBook PreviewSouth Korea AutoBook Preview
South Korea AutoBook Preview
 
Italy AutoBook 2017 Preview
Italy AutoBook 2017 PreviewItaly AutoBook 2017 Preview
Italy AutoBook 2017 Preview
 
EV-AV AutoBook Preview
EV-AV AutoBook PreviewEV-AV AutoBook Preview
EV-AV AutoBook Preview
 

Similar to Dive into SObjectizer 5.5. Eighth Part: Dispatchers

What is SObjectizer 5.7 (at v.5.7.0)
What is SObjectizer 5.7 (at v.5.7.0)What is SObjectizer 5.7 (at v.5.7.0)
What is SObjectizer 5.7 (at v.5.7.0)Yauheni Akhotnikau
 
What is SObjectizer 5.6 (at v.5.6.0)
What is SObjectizer 5.6 (at v.5.6.0)What is SObjectizer 5.6 (at v.5.6.0)
What is SObjectizer 5.6 (at v.5.6.0)Yauheni Akhotnikau
 
This Chapter Will Describe About The Software Requirements...
This Chapter Will Describe About The Software Requirements...This Chapter Will Describe About The Software Requirements...
This Chapter Will Describe About The Software Requirements...Anita Strong
 
Application Of A Macbook Pro And Os X
Application Of A Macbook Pro And Os XApplication Of A Macbook Pro And Os X
Application Of A Macbook Pro And Os XKris Cundiff
 
Javascript spaghetti stirtrek_5_17
Javascript  spaghetti stirtrek_5_17Javascript  spaghetti stirtrek_5_17
Javascript spaghetti stirtrek_5_17Jared Faris
 
RxJava pour Android : présentation lors du GDG Android Montréal
RxJava pour Android : présentation lors du GDG Android MontréalRxJava pour Android : présentation lors du GDG Android Montréal
RxJava pour Android : présentation lors du GDG Android MontréalSidereo
 
Building APIs using Laravel - A simple approach to scale
Building APIs using Laravel - A simple approach to scaleBuilding APIs using Laravel - A simple approach to scale
Building APIs using Laravel - A simple approach to scale🤓 Steve McDougall
 
The Big Picture - Integrating Buzzwords
The Big Picture - Integrating BuzzwordsThe Big Picture - Integrating Buzzwords
The Big Picture - Integrating BuzzwordsAlessandro Giorgetti
 
Essay On Ibm Eclipse Case Study
Essay On Ibm Eclipse Case StudyEssay On Ibm Eclipse Case Study
Essay On Ibm Eclipse Case StudyNicole Hodges
 
Atmosphere Conference 2015: Do you think you're doing microservices?
Atmosphere Conference 2015: Do you think you're doing microservices?Atmosphere Conference 2015: Do you think you're doing microservices?
Atmosphere Conference 2015: Do you think you're doing microservices?PROIDEA
 
Guidelines to understand durable functions with .net core, c# and stateful se...
Guidelines to understand durable functions with .net core, c# and stateful se...Guidelines to understand durable functions with .net core, c# and stateful se...
Guidelines to understand durable functions with .net core, c# and stateful se...Concetto Labs
 
Roboconf Detailed Presentation
Roboconf Detailed PresentationRoboconf Detailed Presentation
Roboconf Detailed PresentationVincent Zurczak
 
Software Requirement Analysis and Thinking Process towards a good Architecture
Software Requirement Analysis and Thinking Process towards a good ArchitectureSoftware Requirement Analysis and Thinking Process towards a good Architecture
Software Requirement Analysis and Thinking Process towards a good Architecturemahmud05
 
Openspasn Interview question.docx
Openspasn Interview question.docxOpenspasn Interview question.docx
Openspasn Interview question.docxShashikumar983614
 

Similar to Dive into SObjectizer 5.5. Eighth Part: Dispatchers (20)

What is SObjectizer 5.7 (at v.5.7.0)
What is SObjectizer 5.7 (at v.5.7.0)What is SObjectizer 5.7 (at v.5.7.0)
What is SObjectizer 5.7 (at v.5.7.0)
 
What is SObjectizer 5.6 (at v.5.6.0)
What is SObjectizer 5.6 (at v.5.6.0)What is SObjectizer 5.6 (at v.5.6.0)
What is SObjectizer 5.6 (at v.5.6.0)
 
This Chapter Will Describe About The Software Requirements...
This Chapter Will Describe About The Software Requirements...This Chapter Will Describe About The Software Requirements...
This Chapter Will Describe About The Software Requirements...
 
Application Of A Macbook Pro And Os X
Application Of A Macbook Pro And Os XApplication Of A Macbook Pro And Os X
Application Of A Macbook Pro And Os X
 
Sdlc
SdlcSdlc
Sdlc
 
Sdlc
SdlcSdlc
Sdlc
 
Javascript spaghetti stirtrek_5_17
Javascript  spaghetti stirtrek_5_17Javascript  spaghetti stirtrek_5_17
Javascript spaghetti stirtrek_5_17
 
RxJava pour Android : présentation lors du GDG Android Montréal
RxJava pour Android : présentation lors du GDG Android MontréalRxJava pour Android : présentation lors du GDG Android Montréal
RxJava pour Android : présentation lors du GDG Android Montréal
 
Building APIs using Laravel - A simple approach to scale
Building APIs using Laravel - A simple approach to scaleBuilding APIs using Laravel - A simple approach to scale
Building APIs using Laravel - A simple approach to scale
 
The Big Picture - Integrating Buzzwords
The Big Picture - Integrating BuzzwordsThe Big Picture - Integrating Buzzwords
The Big Picture - Integrating Buzzwords
 
Essay On Ibm Eclipse Case Study
Essay On Ibm Eclipse Case StudyEssay On Ibm Eclipse Case Study
Essay On Ibm Eclipse Case Study
 
Atmosphere Conference 2015: Do you think you're doing microservices?
Atmosphere Conference 2015: Do you think you're doing microservices?Atmosphere Conference 2015: Do you think you're doing microservices?
Atmosphere Conference 2015: Do you think you're doing microservices?
 
Guidelines to understand durable functions with .net core, c# and stateful se...
Guidelines to understand durable functions with .net core, c# and stateful se...Guidelines to understand durable functions with .net core, c# and stateful se...
Guidelines to understand durable functions with .net core, c# and stateful se...
 
Go With The Flow
Go With The FlowGo With The Flow
Go With The Flow
 
Roboconf Detailed Presentation
Roboconf Detailed PresentationRoboconf Detailed Presentation
Roboconf Detailed Presentation
 
Spring boot
Spring bootSpring boot
Spring boot
 
Software Requirement Analysis and Thinking Process towards a good Architecture
Software Requirement Analysis and Thinking Process towards a good ArchitectureSoftware Requirement Analysis and Thinking Process towards a good Architecture
Software Requirement Analysis and Thinking Process towards a good Architecture
 
Openspasn Interview question.docx
Openspasn Interview question.docxOpenspasn Interview question.docx
Openspasn Interview question.docx
 
Mobile testing android
Mobile testing   androidMobile testing   android
Mobile testing android
 
Raptor 2
Raptor 2Raptor 2
Raptor 2
 

More from Yauheni Akhotnikau

Actor Model and C++: what, why and how? (March 2020 Edition)
Actor Model and C++: what, why and how? (March 2020 Edition)Actor Model and C++: what, why and how? (March 2020 Edition)
Actor Model and C++: what, why and how? (March 2020 Edition)Yauheni Akhotnikau
 
[C++ CoreHard Autumn 2018] Actors vs CSP vs Task...
[C++ CoreHard Autumn 2018] Actors vs CSP vs Task...[C++ CoreHard Autumn 2018] Actors vs CSP vs Task...
[C++ CoreHard Autumn 2018] Actors vs CSP vs Task...Yauheni Akhotnikau
 
Shrimp: A Rather Practical Example Of Application Development With RESTinio a...
Shrimp: A Rather Practical Example Of Application Development With RESTinio a...Shrimp: A Rather Practical Example Of Application Development With RESTinio a...
Shrimp: A Rather Practical Example Of Application Development With RESTinio a...Yauheni Akhotnikau
 
Акторы в C++: взгляд старого практикующего актородела (St. Petersburg C++ Use...
Акторы в C++: взгляд старого практикующего актородела (St. Petersburg C++ Use...Акторы в C++: взгляд старого практикующего актородела (St. Petersburg C++ Use...
Акторы в C++: взгляд старого практикующего актородела (St. Petersburg C++ Use...Yauheni Akhotnikau
 
Акторы на C++: стоило ли оно того?
Акторы на C++: стоило ли оно того?Акторы на C++: стоило ли оно того?
Акторы на C++: стоило ли оно того?Yauheni Akhotnikau
 
25 Years of C++ History Flashed in Front of My Eyes
25 Years of C++ History Flashed in Front of My Eyes25 Years of C++ History Flashed in Front of My Eyes
25 Years of C++ History Flashed in Front of My EyesYauheni Akhotnikau
 
GECon 2017: C++ - a Monster that no one likes but that will outlast them all
GECon 2017: C++ - a Monster that no one likes but that will outlast them allGECon 2017: C++ - a Monster that no one likes but that will outlast them all
GECon 2017: C++ - a Monster that no one likes but that will outlast them allYauheni Akhotnikau
 
Actor Model and C++: what, why and how?
Actor Model and C++: what, why and how?Actor Model and C++: what, why and how?
Actor Model and C++: what, why and how?Yauheni Akhotnikau
 
Шишки, набитые за 15 лет использования акторов в C++
Шишки, набитые за 15 лет использования акторов в C++Шишки, набитые за 15 лет использования акторов в C++
Шишки, набитые за 15 лет использования акторов в C++Yauheni Akhotnikau
 
Для чего мы делали свой акторный фреймворк и что из этого вышло?
Для чего мы делали свой акторный фреймворк и что из этого вышло?Для чего мы делали свой акторный фреймворк и что из этого вышло?
Для чего мы делали свой акторный фреймворк и что из этого вышло?Yauheni Akhotnikau
 
Модель акторов и C++ что, зачем и как?
Модель акторов и C++ что, зачем и как?Модель акторов и C++ что, зачем и как?
Модель акторов и C++ что, зачем и как?Yauheni Akhotnikau
 
What's new in SObjectizer 5.5.9
What's new in SObjectizer 5.5.9What's new in SObjectizer 5.5.9
What's new in SObjectizer 5.5.9Yauheni Akhotnikau
 
Погружение в SObjectizer 5.5. Вводная часть
Погружение в SObjectizer 5.5. Вводная частьПогружение в SObjectizer 5.5. Вводная часть
Погружение в SObjectizer 5.5. Вводная частьYauheni Akhotnikau
 

More from Yauheni Akhotnikau (14)

Actor Model and C++: what, why and how? (March 2020 Edition)
Actor Model and C++: what, why and how? (March 2020 Edition)Actor Model and C++: what, why and how? (March 2020 Edition)
Actor Model and C++: what, why and how? (March 2020 Edition)
 
[C++ CoreHard Autumn 2018] Actors vs CSP vs Task...
[C++ CoreHard Autumn 2018] Actors vs CSP vs Task...[C++ CoreHard Autumn 2018] Actors vs CSP vs Task...
[C++ CoreHard Autumn 2018] Actors vs CSP vs Task...
 
Shrimp: A Rather Practical Example Of Application Development With RESTinio a...
Shrimp: A Rather Practical Example Of Application Development With RESTinio a...Shrimp: A Rather Practical Example Of Application Development With RESTinio a...
Shrimp: A Rather Practical Example Of Application Development With RESTinio a...
 
Акторы в C++: взгляд старого практикующего актородела (St. Petersburg C++ Use...
Акторы в C++: взгляд старого практикующего актородела (St. Petersburg C++ Use...Акторы в C++: взгляд старого практикующего актородела (St. Petersburg C++ Use...
Акторы в C++: взгляд старого практикующего актородела (St. Petersburg C++ Use...
 
Акторы на C++: стоило ли оно того?
Акторы на C++: стоило ли оно того?Акторы на C++: стоило ли оно того?
Акторы на C++: стоило ли оно того?
 
25 Years of C++ History Flashed in Front of My Eyes
25 Years of C++ History Flashed in Front of My Eyes25 Years of C++ History Flashed in Front of My Eyes
25 Years of C++ History Flashed in Front of My Eyes
 
GECon 2017: C++ - a Monster that no one likes but that will outlast them all
GECon 2017: C++ - a Monster that no one likes but that will outlast them allGECon 2017: C++ - a Monster that no one likes but that will outlast them all
GECon 2017: C++ - a Monster that no one likes but that will outlast them all
 
Actor Model and C++: what, why and how?
Actor Model and C++: what, why and how?Actor Model and C++: what, why and how?
Actor Model and C++: what, why and how?
 
Шишки, набитые за 15 лет использования акторов в C++
Шишки, набитые за 15 лет использования акторов в C++Шишки, набитые за 15 лет использования акторов в C++
Шишки, набитые за 15 лет использования акторов в C++
 
Для чего мы делали свой акторный фреймворк и что из этого вышло?
Для чего мы делали свой акторный фреймворк и что из этого вышло?Для чего мы делали свой акторный фреймворк и что из этого вышло?
Для чего мы делали свой акторный фреймворк и что из этого вышло?
 
Модель акторов и C++ что, зачем и как?
Модель акторов и C++ что, зачем и как?Модель акторов и C++ что, зачем и как?
Модель акторов и C++ что, зачем и как?
 
What's new in SObjectizer 5.5.9
What's new in SObjectizer 5.5.9What's new in SObjectizer 5.5.9
What's new in SObjectizer 5.5.9
 
Погружение в SObjectizer 5.5. Вводная часть
Погружение в SObjectizer 5.5. Вводная частьПогружение в SObjectizer 5.5. Вводная часть
Погружение в SObjectizer 5.5. Вводная часть
 
Обзор SObjectizer 5.5
Обзор SObjectizer 5.5Обзор SObjectizer 5.5
Обзор SObjectizer 5.5
 

Recently uploaded

Splashtop Enterprise Brochure - Remote Computer Access and Remote Support Sof...
Splashtop Enterprise Brochure - Remote Computer Access and Remote Support Sof...Splashtop Enterprise Brochure - Remote Computer Access and Remote Support Sof...
Splashtop Enterprise Brochure - Remote Computer Access and Remote Support Sof...Splashtop Inc
 
Mobile App Development company Houston
Mobile  App  Development  company HoustonMobile  App  Development  company Houston
Mobile App Development company Houstonjennysmithusa549
 
If your code could speak, what would it tell you? Let GitHub Copilot Chat hel...
If your code could speak, what would it tell you? Let GitHub Copilot Chat hel...If your code could speak, what would it tell you? Let GitHub Copilot Chat hel...
If your code could speak, what would it tell you? Let GitHub Copilot Chat hel...Maxim Salnikov
 
User Experience Designer | Kaylee Miller Resume
User Experience Designer | Kaylee Miller ResumeUser Experience Designer | Kaylee Miller Resume
User Experience Designer | Kaylee Miller ResumeKaylee Miller
 
03.2024_North America VMUG Optimizing RevOps using the power of ChatGPT in Ma...
03.2024_North America VMUG Optimizing RevOps using the power of ChatGPT in Ma...03.2024_North America VMUG Optimizing RevOps using the power of ChatGPT in Ma...
03.2024_North America VMUG Optimizing RevOps using the power of ChatGPT in Ma...jackiepotts6
 
Large Scale Architecture -- The Unreasonable Effectiveness of Simplicity
Large Scale Architecture -- The Unreasonable Effectiveness of SimplicityLarge Scale Architecture -- The Unreasonable Effectiveness of Simplicity
Large Scale Architecture -- The Unreasonable Effectiveness of SimplicityRandy Shoup
 
Steps to Successfully Hire Ionic Developers
Steps to Successfully Hire Ionic DevelopersSteps to Successfully Hire Ionic Developers
Steps to Successfully Hire Ionic Developersmichealwillson701
 
Flutter the Future of Mobile App Development - 5 Crucial Reasons.pdf
Flutter the Future of Mobile App Development - 5 Crucial Reasons.pdfFlutter the Future of Mobile App Development - 5 Crucial Reasons.pdf
Flutter the Future of Mobile App Development - 5 Crucial Reasons.pdfMind IT Systems
 
Technical improvements. Reasons. Methods. Estimations. CJ
Technical improvements.  Reasons. Methods. Estimations. CJTechnical improvements.  Reasons. Methods. Estimations. CJ
Technical improvements. Reasons. Methods. Estimations. CJpolinaucc
 
Boost Efficiency: Sabre API Integration Made Easy
Boost Efficiency: Sabre API Integration Made EasyBoost Efficiency: Sabre API Integration Made Easy
Boost Efficiency: Sabre API Integration Made Easymichealwillson701
 
8 key point on optimizing web hosting services in your business.pdf
8 key point on optimizing web hosting services in your business.pdf8 key point on optimizing web hosting services in your business.pdf
8 key point on optimizing web hosting services in your business.pdfOffsiteNOC
 
BusinessGPT - SECURITY AND GOVERNANCE FOR GENERATIVE AI.pptx
BusinessGPT  - SECURITY AND GOVERNANCE  FOR GENERATIVE AI.pptxBusinessGPT  - SECURITY AND GOVERNANCE  FOR GENERATIVE AI.pptx
BusinessGPT - SECURITY AND GOVERNANCE FOR GENERATIVE AI.pptxAGATSoftware
 
Enterprise Content Managements Solutions
Enterprise Content Managements SolutionsEnterprise Content Managements Solutions
Enterprise Content Managements SolutionsIQBG inc
 
Revolutionize Your Field Service Management with FSM Grid
Revolutionize Your Field Service Management with FSM GridRevolutionize Your Field Service Management with FSM Grid
Revolutionize Your Field Service Management with FSM GridMathew Thomas
 
Take Advantage of Mx Tracking Flight Scheduling Solutions to Streamline Your ...
Take Advantage of Mx Tracking Flight Scheduling Solutions to Streamline Your ...Take Advantage of Mx Tracking Flight Scheduling Solutions to Streamline Your ...
Take Advantage of Mx Tracking Flight Scheduling Solutions to Streamline Your ...MyFAA
 
MinionLabs_Mr. Gokul Srinivas_Young Entrepreneur
MinionLabs_Mr. Gokul Srinivas_Young EntrepreneurMinionLabs_Mr. Gokul Srinivas_Young Entrepreneur
MinionLabs_Mr. Gokul Srinivas_Young EntrepreneurPriyadarshini T
 
VuNet software organisation powerpoint deck
VuNet software organisation powerpoint deckVuNet software organisation powerpoint deck
VuNet software organisation powerpoint deckNaval Singh
 
Practical Advice for FDA’s 510(k) Requirements.pdf
Practical Advice for FDA’s 510(k) Requirements.pdfPractical Advice for FDA’s 510(k) Requirements.pdf
Practical Advice for FDA’s 510(k) Requirements.pdfICS
 
openEuler Community Overview - a presentation showing the current scale
openEuler Community Overview - a presentation showing the current scaleopenEuler Community Overview - a presentation showing the current scale
openEuler Community Overview - a presentation showing the current scaleShane Coughlan
 

Recently uploaded (20)

Splashtop Enterprise Brochure - Remote Computer Access and Remote Support Sof...
Splashtop Enterprise Brochure - Remote Computer Access and Remote Support Sof...Splashtop Enterprise Brochure - Remote Computer Access and Remote Support Sof...
Splashtop Enterprise Brochure - Remote Computer Access and Remote Support Sof...
 
Mobile App Development company Houston
Mobile  App  Development  company HoustonMobile  App  Development  company Houston
Mobile App Development company Houston
 
20140812 - OBD2 Solution
20140812 - OBD2 Solution20140812 - OBD2 Solution
20140812 - OBD2 Solution
 
If your code could speak, what would it tell you? Let GitHub Copilot Chat hel...
If your code could speak, what would it tell you? Let GitHub Copilot Chat hel...If your code could speak, what would it tell you? Let GitHub Copilot Chat hel...
If your code could speak, what would it tell you? Let GitHub Copilot Chat hel...
 
User Experience Designer | Kaylee Miller Resume
User Experience Designer | Kaylee Miller ResumeUser Experience Designer | Kaylee Miller Resume
User Experience Designer | Kaylee Miller Resume
 
03.2024_North America VMUG Optimizing RevOps using the power of ChatGPT in Ma...
03.2024_North America VMUG Optimizing RevOps using the power of ChatGPT in Ma...03.2024_North America VMUG Optimizing RevOps using the power of ChatGPT in Ma...
03.2024_North America VMUG Optimizing RevOps using the power of ChatGPT in Ma...
 
Large Scale Architecture -- The Unreasonable Effectiveness of Simplicity
Large Scale Architecture -- The Unreasonable Effectiveness of SimplicityLarge Scale Architecture -- The Unreasonable Effectiveness of Simplicity
Large Scale Architecture -- The Unreasonable Effectiveness of Simplicity
 
Steps to Successfully Hire Ionic Developers
Steps to Successfully Hire Ionic DevelopersSteps to Successfully Hire Ionic Developers
Steps to Successfully Hire Ionic Developers
 
Flutter the Future of Mobile App Development - 5 Crucial Reasons.pdf
Flutter the Future of Mobile App Development - 5 Crucial Reasons.pdfFlutter the Future of Mobile App Development - 5 Crucial Reasons.pdf
Flutter the Future of Mobile App Development - 5 Crucial Reasons.pdf
 
Technical improvements. Reasons. Methods. Estimations. CJ
Technical improvements.  Reasons. Methods. Estimations. CJTechnical improvements.  Reasons. Methods. Estimations. CJ
Technical improvements. Reasons. Methods. Estimations. CJ
 
Boost Efficiency: Sabre API Integration Made Easy
Boost Efficiency: Sabre API Integration Made EasyBoost Efficiency: Sabre API Integration Made Easy
Boost Efficiency: Sabre API Integration Made Easy
 
8 key point on optimizing web hosting services in your business.pdf
8 key point on optimizing web hosting services in your business.pdf8 key point on optimizing web hosting services in your business.pdf
8 key point on optimizing web hosting services in your business.pdf
 
BusinessGPT - SECURITY AND GOVERNANCE FOR GENERATIVE AI.pptx
BusinessGPT  - SECURITY AND GOVERNANCE  FOR GENERATIVE AI.pptxBusinessGPT  - SECURITY AND GOVERNANCE  FOR GENERATIVE AI.pptx
BusinessGPT - SECURITY AND GOVERNANCE FOR GENERATIVE AI.pptx
 
Enterprise Content Managements Solutions
Enterprise Content Managements SolutionsEnterprise Content Managements Solutions
Enterprise Content Managements Solutions
 
Revolutionize Your Field Service Management with FSM Grid
Revolutionize Your Field Service Management with FSM GridRevolutionize Your Field Service Management with FSM Grid
Revolutionize Your Field Service Management with FSM Grid
 
Take Advantage of Mx Tracking Flight Scheduling Solutions to Streamline Your ...
Take Advantage of Mx Tracking Flight Scheduling Solutions to Streamline Your ...Take Advantage of Mx Tracking Flight Scheduling Solutions to Streamline Your ...
Take Advantage of Mx Tracking Flight Scheduling Solutions to Streamline Your ...
 
MinionLabs_Mr. Gokul Srinivas_Young Entrepreneur
MinionLabs_Mr. Gokul Srinivas_Young EntrepreneurMinionLabs_Mr. Gokul Srinivas_Young Entrepreneur
MinionLabs_Mr. Gokul Srinivas_Young Entrepreneur
 
VuNet software organisation powerpoint deck
VuNet software organisation powerpoint deckVuNet software organisation powerpoint deck
VuNet software organisation powerpoint deck
 
Practical Advice for FDA’s 510(k) Requirements.pdf
Practical Advice for FDA’s 510(k) Requirements.pdfPractical Advice for FDA’s 510(k) Requirements.pdf
Practical Advice for FDA’s 510(k) Requirements.pdf
 
openEuler Community Overview - a presentation showing the current scale
openEuler Community Overview - a presentation showing the current scaleopenEuler Community Overview - a presentation showing the current scale
openEuler Community Overview - a presentation showing the current scale
 

Dive into SObjectizer 5.5. Eighth Part: Dispatchers

  • 1. Dive into SObjectizer-5.5 SObjectizer Team, Jan 2016 Eighth Part: Dispatchers (at v.5.5.15)
  • 2. This is the next part of the series of presentations with deep introduction into features of SObjectizer-5.5. This part is dedicated to dispatchers which are one of the cornerstones of SObjectizer. Dispatchers play a significant role in the behaviour of any SObjectizer-based application. Because of that understanding of dispatcher concept is necessary for usage of SObjectizer framework. SObjectizer Team, Jan 2016
  • 3. What Is A Dispatcher? SObjectizer Team, Jan 2016
  • 4. Long story short: Dispatchers manage event queues and provide working threads on which agents handle their events. If you don't understand what does it mean, don't worry. There is a slightly longer explanation... SObjectizer Team, Jan 2016
  • 5. The main form of agents interaction in SObjectizer is asynchronous message passing. An agent sends a message to some mbox. If there is a subscriber for that message type on that mbox then an event is created. An event is an info about a specific message which must be delivered to the specific agent. Event are stored in events queue. SObjectizer Team, Jan 2016
  • 6. An event must be extracted from event queue and the message from that event must be passed to agent-receiver for processing. Agent-receiver processes message by event handler which is subscribed to this message type. Event handler is represented by agent's method or just lambda-function. Event handler is called on the context of some thread of execution. This thread is provided by dispatcher. SObjectizer Team, Jan 2016
  • 7. Every working thread on the context of which an event handler is invoked belongs to some dispatcher. So a dispatcher can be seen as manager of working threads to be used for invocation of event handlers. Creation and deletion of working threads is an area of responsibility of dispatcher. SObjectizer Team, Jan 2016
  • 8. There could be many dispatchers in SObjectizer Environment. Each of them will have its own set of working threads. Every agent should be bound to some dispatcher. Binding is done during registration of agent's coop. A programmer can select a dispatcher for a specific agent. Once agent is bound to a dispatcher all agent's events will be handled on working threads of that dispatcher. SObjectizer Team, Jan 2016
  • 9. A dispatcher is not only a manager for working threads. It also manages event queues for agents which are bound to that dispatcher. It is a significant difference of SObjectizer from other actor frameworks: an event queue doesn't belong to an agent. A queue is created and managed by dispatcher. SObjectizer Team, Jan 2016
  • 10. Another difference of SObjectizer from other actor framework is a quantity of event queues. In the "classical" actor-based approach every actor has its own queue with messages to be processed. In SObjectizer a dispatcher makes decision how many event queues are necessary for serving agents bound to that dispatcher. SObjectizer Team, Jan 2016
  • 11. The simplest dispatcher type in SObjectizer, one_thread dispatcher, uses just one event queue for all agents bound to that dispatcher. Much more complex dispatchers like thread_pool and adv_thread_pool can create as many event queues as it required by a programmer. Because of that every dispatcher has its own logic of handling event queues and dispatching events for processing by agents. SObjectizer Team, Jan 2016
  • 12. So now we can say that dispatcher is responsible for: ● creation and deletion of working threads; ● creation and deletion of event queues; ● extraction of events from event queues and invocation of event-handlers on context of dispatcher's working threads. Different dispatchers do these action differently. So a user can choose the most appropriate dispatcher for a particular task. SObjectizer Team, Jan 2016
  • 13. Why Do We Need Dispatchers? SObjectizer Team, Jan 2016
  • 14. For what purpose does SObjectizer support different kinds of dispatchers and allow to create several dispatchers in an application? Why a simple approach with one thread pool for all agents is not used? For what reasons a user should take care about dispatcher and bind agents to some dispatcher? SObjectizer Team, Jan 2016
  • 15. It is a direct consequence of SObjectizer's primary target: simplification of development of multithreading application. SObjectizer doesn't hide threads from user. But simplifies their usage and provides a way for safe interaction between threads via asynchronous message passing. SObjectizer Team, Jan 2016
  • 16. A user may require dedicated threads for performing long and CPU-intensive calculations in background. Or dedicated threads might be necessary for interaction with some hardware attached to your computer. Or dedicated threads might be needed to do blocking calls to some 3rd party library. Or thread pool can be necessary for efficient processing of some event stream. SObjectizer Team, Jan 2016
  • 17. So there can be different reasons to use threads for solving some real-world problems. What we can do with that? We can create and manage working threads manually. We can pass information between threads via some ad-hoc implementations of event queues or synchronize access to shared data via low-level mechanisms like semaphores, mutexes, condition variables and so on... SObjectizer Team, Jan 2016
  • 18. Or we can get a ready-to-use tools for management of working threads and inter-thread message passing. SObjectizer provides such tools: ● working thread management and events scheduling is done via dispatchers; ● inter-thread message passing is implemented via general message delivery mechanism (mboxes, event subscriptions and so on). SObjectizer Team, Jan 2016
  • 19. And because different users require different thread management policies there are different dispatchers in SObjectizer. And because of that there is a possibility to create any number of dispatchers in an application. All of that should allow to user to solve its domain-specific task by most appropriate way. SObjectizer Team, Jan 2016
  • 20. But it doesn't mean that a user must take care about a dispatcher for every agent. A user can take care if he wants. But if not... ...there are such things as default dispatcher and coop's main dispatcher binder which significantly simplify working with SObjectizer. SObjectizer Team, Jan 2016
  • 21. An SObjectizer Environment has the default dispatcher. It is created and started automatically. The default dispatcher is an instance of one_thread dispatcher. It means that all agents bound to that dispatcher will work on the same working thread. If a user doesn't specify a dispatcher for agent or agent's coop then agent will be bound to the default dispatcher. SObjectizer Team, Jan 2016
  • 23. A binding of an agent to a dispatcher is done via separate object called dispatcher binder. Dispatcher binder knows how to bind agent to dispatcher instance during agent registration. And how unbind the agent during deregistration. Every dispatcher implements its own dispatcher binder. It means that if a user wants to bind agent to active_obj dispatcher instance the user must create an active_obj dispatcher binder. SObjectizer Team, Jan 2016
  • 24. Binder can be specified for an agent during agent creation: auto coop = env.create_coop( so_5::autoname ); // An agent will be bound to one_thread dispatcher with name "Monitor". coop->make_agent_with_binder< some_agent_type >( // Creation of dispatcher binder. so_5::disp::one_thread::create_disp_binder( "Monitor" ), ... /* Args for some_agent_type constructor */ ); // An agent will be bound to active_obj dispatcher witn name "Handler". coop->make_agent_with_binder< some_agent_type >( so_5::disp::active_obj::create_disp_binder( "Handler" ), ... ); SObjectizer Team, Jan 2016
  • 25. Binder can also be specified for the whole coop. Such binder will be main binder for that coop: auto coop = env.create_coop( so_5::autoname, // A main binder for coop will be a binder to active_obj dispatcher with the name "Handler". so_5::disp::active_obj::create_disp_binder( "Handler" ) ); // This agent will be bound via coop's main binder to active_obj dispatcher with the name "Handler". coop->make_agent< some_agent_type >( ... ); // This agent will also be bound to active_obj dispatcher with the name "Handler". coop->make_agent< another_agent_type >( ... ); // But this agent will be bound to one_thread dispatcher with the name "Monitor". It is because // a separate dispatcher binder is set for that agent. coop->make_agent_with_binder< some_agent_type >( so_5::disp::one_thread::create_disp_binder( "Monitor" ), ... ); SObjectizer Team, Jan 2016
  • 26. If a dispatcher binder is not set for a coop then a binder for the default dispatcher will be used as main binder for that coop. SObjectizer Team, Jan 2016
  • 27. Public And Private Dispatchers SObjectizer Team, Jan 2016
  • 28. There are two kinds of dispatchers in SObjectizer: public and private. There are important differences in how to work with them. SObjectizer Team, Jan 2016
  • 29. Public dispatchers must have unique names. They are accessed by means of their names. Once created public dispatchers stay inside SObjectizer Environment until Environment finished its work. It means that an instance of public dispatcher will work even when no one is using it. SObjectizer Team, Jan 2016
  • 30. Private dispatchers are accessible only via direct references obtained during dispatchers creation. Private dispatchers are destroyed automatically when no one uses them. SObjectizer Team, Jan 2016
  • 31. A public dispatcher instance is passed to SObjectizer Environment via environment_params_t object which could be tuned in the launch() function: so_5::launch( []( so_5::environment_t & ) { ... }, // Environment's parameters tuning lambda. []( so_5::environment_params_t & params ) { // Addition of a public active_obj dispatcher with the name "Handler". params.named_dispatcher( "Handler", so_5::disp::active_obj::create_disp() ); // Addition of a public one_thread dispatcher with the name "Monitor". params.named_dispatcher( "Monitor", so_5::disp::one_thread::create_disp() ); } ); SObjectizer Team, Jan 2016
  • 32. Another way of creation of a public dispatcher instance is the usage of add_dispatcher_if_not_exists method: void my_agent::evt_long_request( const request & evt ) { // New child cooperation is necessary for handling the request. // An instance of dispatcher is required for the cooperation. // Create a dispatcher if it doesn't exist. so_environment().add_dispatcher_if_not_exists( "request_handler", [] { return so_5::disp::active_group::create_disp(); } ); so_5::introduce_child_coop( *this, so_5::disp::active_group::create_disp_binder( "request_handler" ), [&]( so_5::coop_t & coop ) { ... } ); } SObjectizer Team, Jan 2016
  • 33. A binder for public dispatcher is created via appropriate create_disp_binder() function which receives the name of the dispatcher: auto coop = env.create_coop( so_5::autoname, // A main binder for coop will be a binder to active_obj dispatcher with name "Handler". so_5::disp::active_obj::create_disp_binder( "Handler" ) ); ... // This agent will be bound to one_thread dispatcher with name "Monitor". It is because // a personal dispatcher binder is set for that agent. coop->make_agent_with_binder< some_agent_type >( so_5::disp::one_thread::create_disp_binder( "Monitor" ), ... ); SObjectizer Team, Jan 2016
  • 34. An instance of private dispatcher is created by appropriate create_private_disp() which is implemented for every standard dispatcher type in SObjectizer. A kind of smart pointer is returned by create_private_disp() function. This handle can be used for binding agents for that private dispatcher instance. The instance will be destroyed automatically when no one uses this handle anymore. SObjectizer Team, Jan 2016
  • 35. An example of creating private dispatchers: auto coop = env.create_coop( so_5::autoname, // A main binder for coop will be a binder to a private active_obj dispatcher. so_5::disp::active_obj::create_private_disp( env )->binder() ); // This agent will be bound via coop's main binder to active_obj dispatcher. coop->make_agent< some_agent_type >( ... ); // This agent will also be bound to active_obj dispatcher. coop->make_agent< another_agent_type >( ... ); // But this agent will be bound to private one_thread dispatcher. coop->make_agent_with_binder< some_agent_type >( so_5::disp::one_thread::create_private_disp( env )->binder(), ... ); SObjectizer Team, Jan 2016
  • 36. Public dispatchers were created in the very first versions of SObjectizer and they have some limitations. For example there is no way to stop a public dispatcher if no one uses it. Private dispatchers were added later and they solve some problems related to public dispatchers. Because of that usage of private dispatchers is preferable. SObjectizer Team, Jan 2016
  • 37. Event Handler Thread Safety SObjectizer Team, Jan 2016
  • 38. All event handlers are treated as not thread safe by default. It means that if there are events E1 and E2 in event queue for some agent A then these events will be delivered to A one after another. It is impossible that event handler for E1 is running at the same time as event handler for E2 but on different thread. SObjectizer guarantees that one event handler completed its execution and only then the next event handler will be called. SObjectizer Team, Jan 2016
  • 39. Thread safety has sense on dispatchers which use pools of threads. Such dispatchers can migrate an agent from one working thread to another. Because such migration can take place the SObjectizer's thread safety guarantee simplifies development of agents: there is no need for synchronization of access to agent's internals by using locks or something like that. SObjectizer Team, Jan 2016
  • 40. User can mark an event handler as thread safe. For example if event handler doesn't modify state of the agent. Or if such modification is implemented via usage of appropriate mechanism like mutex or spinlock. Most of standard SObjectizer's dispatchers will ignore that mark and will treat every event handler as thread unsafe. But there is adv_thread_pool dispatcher which can use that mark appropriately. SObjectizer Team, Jan 2016
  • 41. When agent is bound to adv_thread_pool dispatcher and event handler H is marked as thread safe then the dispatcher can schedule calls of H for different events on several of working threads at the same time. Moreover if agent has thread safe event handler H and not thread safe event handler G then adv_thread_pool will guarantee that all event handlers H will finish its work before a single event handler G will be invoked. SObjectizer Team, Jan 2016
  • 42. At v.5.5.15 there is only one dispatcher which can distinguish between not thread safe and thread safe event handlers. But more dispatchers with such abilities can be introduced in the future versions of SObjectizer. SObjectizer Team, Jan 2016
  • 43. A Brief Overview Of Existing Dispatchers SObjectizer Team, Jan 2016
  • 44. There are eight standard dispatchers in SObjectizer-5.5 Five of them do not support agent's priorities: one_thread, active_obj, active_group, thread_pool and adv_thread_pool. These dispatcher think that all agents have the same priority. Three dispatchers support agent's priorities: prio_one_thread::strictly_ordered, prio_one_thread:: quoted_round_robin, prio_dedicated_threads::one_per_prio. They schedule agents with respect to agent's priority. SObjectizer Team, Jan 2016
  • 45. All stuff related to some dispatcher is defined in a specific namespace inside so_5::disp. For example: so_5::disp::active_obj so_5::disp::thread_pool so_5::disp::prio_one_thread::strictly_ordered SObjectizer Team, Jan 2016
  • 46. Every dispatcher-specific namespace has the similar set of functions and classes like: create_disp, create_private_disp, create_disp_binder queue_params_t, disp_params_t, bind_params_t This makes usage of different dispatchers very similar: if you know how to create one_thread dispatcher you easily create create active_obj or thread_pool dispatcher. SObjectizer Team, Jan 2016
  • 48. one_thread dispatcher is the oldest, simplest and, sometimes, most useful dispatcher. It creates just one working thread and just one event queue. Events for all agents bound to that dispatcher are stored in single event queue. The single working thread gets the next event from the queue and runs event handler form agent-receiver. Then gets the next event and so on. SObjectizer Team, Jan 2016
  • 49. It is possible to say that one_thread implements cooperative multitasking: if some agent hangs then all other agents bound to that dispatcher will hang too. SObjectizer Team, Jan 2016
  • 51. active_obj is another very old and simple dispatcher. But now, after addition of private dispatchers to SObjectizer, it is less useful than before. active_obj dispatcher creates a separate working thread and separate event queue for every agent bound to that dispatcher. It means that every agent will have its own working thread and its own event queue. SObjectizer Team, Jan 2016
  • 52. active_obj dispatcher creates a new event queue and launches a new working thread for every agent bound to it. When agent is deregistered the dispatcher stops the working thread of this agent and deletes the corresponding event queue. It means that if there are no agents bound to active_obj dispatcher there are no working threads nor event queues. SObjectizer Team, Jan 2016
  • 53. active_obj dispatcher is useful if it is necessary to provide a separate working thread for some agent. For example if agent needs a dedicated context for long- running activities like interaction with hardware devices, performing blocking calls to 3rd party libraries or external systems and so on. The similar effect can be achieved by using a private one_thread dispatcher. But sometimes usage of active_obj dispatcher requires less efforts... SObjectizer Team, Jan 2016
  • 54. An example of usage of active_obj dispatcher: auto coop = env.create_coop( so_5::autoname, // A main binder for coop will be binder to private active_obj dispatcher. // It means that all agents of the coop without explicitly specified // binder will be bound to that active_obj dispatcher and become // active objects with own working thread. so_5::disp::active_obj::create_private_disp( env )->binder() ); for( const auto & d : devices ) // Create a separate agent for every device. coop->make_agent< device_manager >( d ); env.register_coop( std::move(coop) ); SObjectizer Team, Jan 2016
  • 56. active_group is another very old and simple dispatcher. But now, after addition of private dispatchers to SObjectizer, it is less useful than before and can be replaced by private one_thread dispatcher. active_group dispatcher creates a separate working thread and separate event queue for named group of agents. It means that all agents from the same group will work on a common working thread. SObjectizer Team, Jan 2016
  • 57. active_group dispatcher creates a new working thread and a new event queue when the first agent of new group is registered. active_group dispatcher stops group's working thread and destroy group's event queue when the last agent from the group is deregistered. It means that all resources for a group are deallocated when group lost the last member. SObjectizer Team, Jan 2016
  • 58. If a new agent is added to group which disappear earlier a new group with the same name will be created. For example: ● agents A and B is being registered as part of group G1; ● new group G1 is created, new working thread is started for G1; ● agents A and B are deregistered; ● working thread for G1 is stopped, group G1 is deleted; ● agents C and D is being registered as part of group G1; ● new group G1 is created, new working thread is started for G1; SObjectizer Team, Jan 2016
  • 59. Every instance of active_group dispatcher has its own set of active groups. A group name must be unique only inside one dispatcher instance. It means that dispatcher instance ag1 can have group G1 and dispatcher instance ag2 can have group G1 too. These groups will be different. Lifetime of ag1.G1 and ag2. G1 will be independent from each other. SObjectizer Team, Jan 2016
  • 60. active_group dispatcher can be useful if it is necessary to bind a group of agents to the same working thread. For example if these agents performs different stages of complex requests processing. Let's imagine a processing pipeline of three stages: requests params validation, request processing and generation of results. Every of these states can take a long time so it is better to provide a separate context to every request. It can be done by using active_group dispatcher... SObjectizer Team, Jan 2016
  • 61. An example of binding agents to the same active group: std::string request_id = generate_request_id( request ); // Create coop with request ID used as coop name. auto coop = env.create_coop( request_id, // All agents of this coop will be part of active group on // active_group dispatcher with name "Handlers". // request_id will be used as group name. so_5::disp::active_group::create_disp_binder( "Handlers", request_id ) ); // Filling coop with agents. coop->make_agent< request_checker >( request ); coop->make_agent< request_handler >( request ); coop->make_agent< response_generator >( request ); env.register_coop( std::move(coop) ); SObjectizer Team, Jan 2016
  • 62. After addition of private dispatcher to SObjectizer active_group dispatcher can often be replaced by private one_thread dispatcher. But sometimes active_group dispatchers can still be useful. For example if agents for request processing cannot be created at the same time and agent for the next stage can be registered only after completion of the previous state... SObjectizer Team, Jan 2016
  • 63. An example of addition of agents from different coops to the same active group: void request_acceptor::new_request( const request_type & request ) { // A cooperation with the first stage must be created. std::string request_id = generate_request_id( request ); env.introduce_coop( request_id + "-checker", so_5::disp::active_group::create_disp_binder( "Handlers", request_id ), [&]( so_5::coop_t & coop ) { coop.make_agent< request_checker >( request ); } ); } ... void request_checker::check_completed() { // A cooperation with the second stage can be created. std::string request_id = generate_request_id( request ); so_environment().introduce_coop( request_id + "-handler", so_5::disp::active_group::create_disp_binder( "Handlers", request_id ), [&]( so_5::coop_t & coop ) { coop.make_agent< request_handler >( request ); } ); } SObjectizer Team, Jan 2016
  • 65. thread_pool dispatcher creates a pool with several working threads. An agent bound to thread_pool dispatcher can handle its events on any of working threads from that pool. thread_pool dispatcher guarantees that at any given moment only single event handler of the agent might run thus using only one of the working threads. It is impossible to run event handlers e1 and e2 of agent A on different thread at the same time. SObjectizer Team, Jan 2016
  • 66. The most complicated moment in thread_pool dispatcher is event queues. There are two important things which need to be mentioned for understanding of thread_pool dispatcher logic: ● type of FIFO for agent/coop; ● max_demands_at_once parameter. SObjectizer Team, Jan 2016
  • 67. Type of FIFO determines the relationship between event handlers of agents from one coop. Suppose there is a coop with agents A, B and C. Some agent D sends the following messages in exactly that order: ● M1 to A ● M2 to B ● M3 to A ● M4 to C ● M5 to B SObjectizer Team, Jan 2016
  • 68. If agents A, B and C use cooperation FIFO then all these agents will use one common event queue. Sequence of event handler calls will look like: 1. A's event handler for M1 2. B's event handler for M2 3. A's event handler for M3 4. C's event handler for M4 5. B's event handler for M5 Exactly in that order. B's event handler for M2 will be called only when A's event handler for M1 finished its work. SObjectizer Team, Jan 2016
  • 69. Cooperation FIFO also means that agents with that FIFO type cannot work on different threads at the same time. For example it is possible that agent A will handle M1 on thread T1. Then agent B will handle M2 on thread T2. Then agent A will handle M3 on T3. But it is impossible that A will handle M1 on T1 and B will handle M2 on T2 at the same time. SObjectizer Team, Jan 2016
  • 70. If agents A, B and C use individual FIFO then all these agents will use different and independent event queues. It is hard to predict as a sequence of event handlers will look like. For example: 1. A's event handler for M1 on thread T1 2. B's event handler for M2 on thread T2 3. C's event handler for M4 on thread T3 4. B's event handler for M5 on thread T2 5. A's event handler for M3 on thread T1 SObjectizer Team, Jan 2016
  • 71. Individual FIFO also means that agents with that FIFO type can work on different threads in parallel. For example it is possible that agent A will handle M1 on thread T1. At the same time agent B will handle M2 on thread T2. At the same time agent C will handle M4 on thread T3. SObjectizer Team, Jan 2016
  • 72. There is another side of FIFO type: thread safety. If agents from a coop use cooperative FIFO then they do not need to synchronize access to some shared data. Suppose several agents from one coop use common std::map object. Because these agents cannot work on different threads at the same time they can read and modify that object without any mutexes or something like that. But if agents use individual FIFO every shared data must be protected or completely avoided. SObjectizer Team, Jan 2016
  • 73. Parameter max_demands_at_once tells how many events from an event queue can be processed by working thread before switching to processing of another event queue. This parameter is important because every working thread in thread_pool dispatcher works this way: ● gets the next non-empty event queue; ● handle at most max_demands_at_once events from it; ● gets the next non-empty event queue; ● ... SObjectizer Team, Jan 2016
  • 74. Suppose there are agents A, B and C from one coop with cooperation FIFO and events for messages M1, M2, ..., M5 in their event queue.... SObjectizer Team, Jan 2016
  • 75. If max_demands_at_once is 4 then the following scenario might happen: ● some working thread T1 gets this event queue and calls event handlers for messages M1, ..., M4; ● working thread T1 switches for handling different event queue. Event queue for A, B, C agents holds M5; ● some working thread Tn gets this event queue and calls event handler for M5; ● event queue for A, B, C agents becomes empty and Tn switches to another event queue. SObjectizer Team, Jan 2016
  • 76. If max_demands_at_once is 1 then a working thread will handle just one event from A, B, C agent queue. Then this queue can be handled by another working thread which will handle just one event. Then this queue can be handled by another working thread... And so on. SObjectizer Team, Jan 2016
  • 77. A more interesting situation can be if agents A, B and C use individual FIFO. In that case there will be independent queues for these agents: ● a queue for A with M1 and M3; ● a queue for B with M2 and M5; ● a queue for C with M4. SObjectizer Team, Jan 2016
  • 78. If max_demands_at_once is greater than 1 then there could be the following scenario: ● thread T1 handles M1 and M3 for A; ● thread T2 handles M4 for C; ● thread T3 handles M2 and M5 for B. But if there are just two working threads in the pool: ● thread T1 handles M1 and M3 for A; ● thread T2 handles M4 for C; ● thread T1 handles M2 and M5 for B. SObjectizer Team, Jan 2016
  • 79. Value of max_demands_at_once determines how often a working thread will switch from one event queue to another. It can have a huge impact on application performance: small values of max_demands_at_once will lead to frequent queue switching and this will slow down event processing. So large values of max_demands_at_once can speed up event processing if there is a dense flow of events. SObjectizer Team, Jan 2016
  • 80. Implementation of thread_pool dispatcher makes things yet more complex and interesting: every agent for a coop can have its own parameters for thread_pool dispatcher. It means that agent A can have individual FIFO and max_demands_at_once=100, but agents B and C from the same coop will have cooperation FIFO and max_demands_at_once=10. In this case two different event queues will be created: one for A and another for B and C. SObjectizer Team, Jan 2016
  • 81. This complex logic of thread_pool allows precise performance tuning for complex use cases which can be found in real-life problems. But in the simple cases the default parameters can be used (cooperation FIFO and max_demands_at_once=4). This significantly simplifies usage of thread_pool dispatcher. Especially when several coops are bound to the same thread_pool dispatcher instance. SObjectizer Team, Jan 2016
  • 82. An example for thread_pool dispatcher: void init( so_5::environment_t & env ) { using namespace so_5::disp::thread_pool; env.introduce_coop( // Create an instance of thread_pool dispatcher with 3 working threads. create_private_disp( env, 3 )->binder( // All agents will use individual FIFO. // Parameter max_demands_at_once will have the default value. bind_params_t{}.fifo( fifo_t::individual ) ), []( so_5::coop_t & c ) { auto collector = c.make_agent< a_collector_t >(); auto performer = c.make_agent< a_performer_t >( collector->so_direct_mbox() ); collector->set_performer_mbox( performer->so_direct_mbox() ); c.make_agent< a_generator_t >( collector->so_direct_mbox() ); }); } SObjectizer Team, Jan 2016
  • 84. adv_thread_pool dispatcher is similar to thread_pool dispatcher but has two important differences: 1. It allows to invoke several thread safe event handlers for an agent at the same time on different threads. 2. As a consequence of previous point there is no max_demands_at_once parameter. SObjectizer Team, Jan 2016
  • 85. Every working thread in adv_thread_pool works this way: ● gets some non-empty event queue; ● gets the first event from that queue; ● checks thread safety for event handler for that event; ● checks a possibility of invocation of this event handler; ● if event handler can be invoked it is called; ● if event handler cannot be invoked then event is returned to event queue and thread switches to another non- empty event queue. SObjectizer Team, Jan 2016
  • 86. An event handler for an agent can be called if: ● it is not thread safe and there is no any other event handlers of that agent which are running now on one of the threads; ● or it is thread safe and there is no any not thread safe event handler which is working now on some thread. It means that only one not thread safe event handler can be called. And next event handler can be called only after completion of previous handler. Several thread safe handlers can work at the same time. SObjectizer Team, Jan 2016
  • 87. There are two types of FIFO for adv_thread_pool: cooperation and individual. Just like in thread_pool dispatcher. But in adv_thread_pool FIFO type has influence on checking for thread safety of event handler. Suppose there are agents A and B from one coop and they use cooperation FIFO. Suppose also that event handlers A. e1 and B.e2 are thread safe, but event handler A.e3 is not. SObjectizer Team, Jan 2016
  • 88. If there is events e1, e2, e3, e2, e1, e3 in the event queue for A and B agents then event handlers will be called in the following sequence: A.e1 on thread T1, B.e2 on thread T2. Only after completion of event handlers A.e1 and B.e2 event handler A.e3 will be called. Then A.e1 on T1 and B.e2 on T2. Then waiting for completion and the call to A.e3. SObjectizer Team, Jan 2016
  • 89. If agents A and B use individual FIFO and there are events sequence {e1, e3, e1} and {e2, e2} in two event queues then there could be the following scenario: ● A.e1 on T1, then A.e3 on T1, then A.e1 on T1; ● B.e2 on T2; ● B.e2 on T3. SObjectizer Team, Jan 2016
  • 90. adv_thread_pool can be useful for spreading thread safe event processing on several working threads. For example there could be cryptographer agent which performs make_signature, check_signature, encrypt_block and decrypt_block operations. These operations are thread safe because they don't change the state of cryptographer agent. Event handler for these operations can be marked as thread safe. This allows to handle several cryptographic operations at the same time in parallel. SObjectizer Team, Jan 2016
  • 91. Subscription of thread safe event handler: class cryptographer : public so_5::agent_t { void on_make_signature( const make_signature & ) {...} void on_check_signature( const check_signature & ) {...} void on_encrypt_block( const encrypt_block & ) {...} void on_decrypt_block( const decrypt_block & ) {...} ... virtual void so_define_agent() override { so_subscribe_self() .event( &cryptographer::on_make_signature, so_5::thread_safe ) .event( &cryptographer::on_check_signature, so_5::thread_safe ) .event( &cryptographer::on_encrypt_block, so_5::thread_safe ) .event( &cryptographer::on_decrypt_block, so_5::thread_safe ) ... } } SObjectizer Team, Jan 2016
  • 92. An agent can have thread safe and not thread safe event handlers. For example cryptographer agent can have not thread safe event handler for message reconfigure. In this case adv_thread_pool dispatcher guarantees that all thread safe event handlers finish their work before an event handler for reconfigure message will be started. SObjectizer Team, Jan 2016
  • 93. An example of binding agent to adv_thread_pool dispatcher: using namespace so_5::disp::adv_thread_pool; env.introduce_coop( // All agents of new coop will work on adv_thread_pool dispatcher. // Every agent will use individual FIFO. create_private_disp( env, 4 )->binder( bind_params_t{}.fifo( fifo_t::individual ) ), []( so_5::coop_t & coop ) { coop.make_agent< cryptographer >(); ... } ); SObjectizer Team, Jan 2016
  • 95. prio_one_thread::strictly_ordered dispatcher allows for events of high priority agents to block events of low priority agents. It means that events queue is always strictly ordered: events for agents with high priority are placed before events for agents with lower priority. SObjectizer Team, Jan 2016
  • 96. For example if event queue is {e1(a7), e2(a6), e3(a4), e4 (a4)}, where a7 means an agent with priority p7, then events will be handled in exact that order. After handling e1 the queue will be {e2(a6), e3(a4), e4(a4)}. If e5 for a5 arrived then the queue will become {e2(a6), e5 (a5), e3(a4), e4(a4)}. It means that chronological order of events will be preserved only for events of agents with the same priority. SObjectizer Team, Jan 2016
  • 97. This dispatcher could be useful if there is a necessity of handling some messages before other messages. For example there could be a stream of tasks represented by take_job messages. There also could be a special message for task processor’s reconfiguration: new_config message. It could have a sense to handle new_config as soon as possible. SObjectizer Team, Jan 2016
  • 98. This can be done by two agents which are bound to single prio_one_thread::strictly_ordered dispatcher. One agent will have priority p1 and will handle new_config message. Second agent will have priority p0 and will handle take_job. Both agents will have common shared data (at least configuration parameters, may be something else). Dispatcher prio_one_thread::strictly_ordered guarantees that new_config will be handled as soon as processing of previous message finished. SObjectizer Team, Jan 2016
  • 99. An example of binding agents to prio_one_thread:: strictly_ordered dispatcher: namespace prio_disp = so_5::disp::prio_one_thread::strictly_ordered; env.introduce_coop( // Dispatcher instance and binder for it. prio_disp::create_private_disp( env )->binder(), []( so_5::coop_t & coop ) { // An agent with higher priority. coop.make_agent< config_manager >( so_5::prio::p1 ); // An agent with lower priority. coop.make_agent< job_performer >( so_5::prio::p0 ); } ); SObjectizer Team, Jan 2016
  • 101. prio_one_thread::quoted_round_robin dispatcher works on round-robin principle. It allows to specify maximum count of events to be processed consequently for the specified priority. After processing that count of events dispatcher switches to processing events of lower priority even if there are yet more events of higher priority to be processed. SObjectizer Team, Jan 2016
  • 102. Dispatcher handles no more than Q7 events of priority p7, then no more than Q6 events of priority p6, ..., then no more than Q0 events of priority p0. If an event of higher priority is arrived during handling a quote for lower priority no switching is performed. For example if dispatcher handles events of priority p5 and event of priority p7 is arrived the dispatcher will continue to handle events of p5, then events of p4 (if any), ..., then events of p0 (if any). And only then events of p7. SObjectizer Team, Jan 2016
  • 103. This working scheme means that agent’s priorities treated as agent’s weight. A programmer can set bigger quotes for more prioritized (more heavyweight) agents and that agents will receive more resources than less prioritized (less weighted) agents. SObjectizer Team, Jan 2016
  • 104. A very important detail: events of the same priority are handled in chronological order. SObjectizer Team, Jan 2016
  • 105. A dispatcher of that type can be useful, for example, if there are agents which handles clients of different types. Some clients are VIP clients and they should receive first-class quality of service and there could be other clients with lower demands for service quality. A high priority to agents for handling VIP-client requests can be used and a large quote for that priority can be set. All other agents will have lower priority and smaller quote. As result more requests from VIP-clients will be handled but there also will be processing of request from other clients. SObjectizer Team, Jan 2016
  • 106. An example of binding agents to prio_one_thread:: quoted_round_robin dispatcher: namespace prio_disp = so_5::disp::prio_one_thread::quoted_round_robin; env.introduce_coop( // Create dispatcher and define quotes for several priorities. prio_disp::create_private_disp( env, // By default every priority will have quote for 20 events. prio_disp::quotes_t{ 20 } // Priority p7 will have different quote. .set( so_5::prio::p7, 45 ) // Priority p6 will have different quote too. .set( so_5::prio::p6, 35 ) )->binder(), []( so_5::coop_t & coop ) { coop.make_agent< vip_client_processor >( so_5::prio::p7 ); coop.make_agent< ordinal_client_processor >( so_5::prio::p6 ); coop.make_agent< free_client_processor >( so_5::prio::p0 ); } ); SObjectizer Team, Jan 2016
  • 108. prio_dedicated_threads::one_per_prio dispatcher creates a single dedicated thread for every priority. It means that events for agents with priority p7 will be handled on different thread than events for agents with, for example, priority p6. Events of the same priority are handled in chronological order. SObjectizer Team, Jan 2016
  • 109. Because of the fact that priority is assigned to an agent at its creation and cannot be changed later an agent inside prio_dedicated_threads::one_per_prio is bound to a particular working thread and do not moved from that thread to any other thread. This property of the dispatcher can be used for binding processing of different message types to different working threads: messages of type M1 can be processed by agent A1 with priority p1, messages of type M2 -- by agent A2 with priority p2 and so on... SObjectizer Team, Jan 2016
  • 110. Assigning different priorities for agents which handle different message type may have sense if OS-specific API for changing thread priority is used. For example an agent with priority p7 can set higher priority for its working thread in so_evt_start() method than agent with priority p6. SObjectizer Team, Jan 2016
  • 111. An example of binding agents to prio_dedicated_threads:: one_per_prio dispatcher: namespace prio_disp = so_5::disp::prio_dedicated_threads::one_per_prio; env.introduce_coop( // An instance of dispatcher and a binder for it. prio_disp::create_private_disp( env )->binder(), []( so_5::coop_t & coop ) { coop.make_agent< m1_handler >( so_5::prio::p1 ); coop.make_agent< m2_handler >( so_5::prio::p2 ); ... } ); SObjectizer Team, Jan 2016
  • 112. Some Final Words SObjectizer Team, Jan 2016
  • 113. Dispatchers play significant role in application development on top on SObjectizer-5. It is because SObjectizer do not hide multithreading from a user. But simplifies a work with multithreading in application domains where threads are important. Application domains are different. Even inside one domain different event scheduling policies might be needed. This is why SObjectizer provides several dispatcher types. SObjectizer Team, Jan 2016
  • 114. This presentation has no intention to be a comprehensive guide for SObjectizer's dispatcher. It is just an attempt to explain a role of dispatchers and a short overview of standard SObjectizer's dispatcher and their features. For more detailed information please see corresponding sections in the Project's Wiki and materials in the Project's Blog. SObjectizer Team, Jan 2016
  • 115. Additional Information: Project’s home: http://sourceforge.net/projects/sobjectizer Documentation: http://sourceforge.net/p/sobjectizer/wiki/ Forum: http://sourceforge.net/p/sobjectizer/discussion/ Google-group: https://groups.google.com/forum/#!forum/sobjectizer GitHub mirror: https://github.com/masterspline/SObjectizer