SlideShare uma empresa Scribd logo
1 de 119
Baixar para ler offline
Dive into SObjectizer-5.5
SObjectizer Team, Jan 2016
Introductory part
(at v.5.5.15)
SObjectizer is a small framework that simplifies
the development of concurrent and event-driven
applications in C++.
SObjectizer Team, Jan 2016
SObjectizer was designed under the influence of
several approaches. The Actor Model* is one of
them. But the history of SObjectizer started long
before this model became widely known.
*
http://en.wikipedia.org/wiki/Actor_model SObjectizer Team, Jan 2016
SObjectizer’s main ideas and principles were
formulated in the middle of 1990s, during the
development of SCADA Objectizer project in
Development Bureau of System Programming in
Homyel, Belarus (1996-2000).
SCADA Objectizer’s ideas were reused in the new
project SObjectizer-4 in 2002.
SObjectizer Team, Jan 2016
Evolution of SObjectizer-4 was stopped in 2010
and the development of SObjectizer-5 started.
SObjectizer Team, Jan 2016
SObjectizer was an in-house project of
JSC Intervale*
for the long time.
It was used in the development of the following
software systems:
● SMS/USSD traffic service
● financial transaction handling
● software parameters monitoring.
*
www.intervale.ru SObjectizer Team, Jan 2016
SObjectizer was published as an OpenSource
project on SourceForge under 3-clauses BSD-
licence in 2006.
Since 2013 SObjectizer’s development completely
moved to SourceForge.
SObjectizer now is an independent project which is
totally separated from JSC Intervale.
SObjectizer Team, Jan 2016
SObjectizer allows to build a concurrent
application as a set of agent-objects...
...which interact with each other only by means of
asynchronous messages.
SObjectizer Team, Jan 2016
Every agent receives its own working context.
This context is used for message processing.
An agent is bound to its context. It allows not to
worry about defense of integrity of the agent’s
data in the multithreaded environment.
This defense is automatically performed by
SObjectizer itself!
SObjectizer Team, Jan 2016
Let’s dive inside!
SObjectizer Team, Jan 2016
All SObjectizer’s work is performed inside
SObjectizer Environment.
SObjectizer Environment is a container for
SObjectizer Run-Time, agent’s cooperations,
message boxes, dispatchers and timer thread.
It is possible to create several Environments in one
application. Each Environment will work
independently from others.
SObjectizer Team, Jan 2016
SObjectizer Environment is created by
so_5::launch() function.
A new instance of Environment is created and started
inside so_5::launch(). The control from so_5::launch()
is returned only when Environment finished its
execution.
What happened inside Environment is completely
dependent on user supplied starting function.
SObjectizer Team, Jan 2016
It looks like that:
#include <iostream>
#include <so_5/all.hpp>
void init( so_5::environment_t & env ) { ... }
int main()
{
try
{
so_5::launch( &init );
}
catch( const std::exception & x )
{
std::cerr << "Exception: " << x.what() << std::endl;
}
}
SObjectizer Team, Jan 2016
#include <iostream>
#include <so_5/all.hpp>
void init( so_5::environment_t & env ) { ... }
int main()
{
try
{
so_5::launch( &init );
}
catch( const std::exception & x )
{
std::cerr << "Exception: " << x.what() << std::endl;
}
}
Main header file with all
necessary definitions.
It looks like that:
SObjectizer Team, Jan 2016
#include <iostream>
#include <so_5/all.hpp>
void init( so_5::environment_t & env ) { ... }
int main()
{
try
{
so_5::launch( &init );
}
catch( const std::exception & x )
{
std::cerr << "Exception: " << x.what() << std::endl;
}
}
User supplied starting function.
It creates all application specific
stuff.
It looks like that:
SObjectizer Team, Jan 2016
#include <iostream>
#include <so_5/all.hpp>
void init( so_5::environment_t & env ) { ... }
int main()
{
try
{
so_5::launch( &init );
}
catch( const std::exception & x )
{
std::cerr << "Exception: " << x.what() << std::endl;
}
}
SObjectizer Environment object. Starting
function will work inside it.
It looks like that:
SObjectizer Team, Jan 2016
#include <iostream>
#include <so_5/all.hpp>
void init( so_5::environment_t & env ) { ... }
int main()
{
try
{
so_5::launch( &init );
}
catch( const std::exception & x )
{
std::cerr << "Exception: " << x.what() << std::endl;
}
}
Creation of Environment, starting
it and invoking init() inside that
Environment.
Control will be returned when all
application-specific agents finish
their work.
It looks like that:
SObjectizer Team, Jan 2016
#include <iostream>
#include <so_5/all.hpp>
void init( so_5::environment_t & env ) { ... }
int main()
{
try
{
so_5::launch( &init );
}
catch( const std::exception & x )
{
std::cerr << "Exception: " << x.what() << std::endl;
}
}
Error handling. Error reporting is done via
exceptions.
It looks like that:
SObjectizer Team, Jan 2016
Usually one or more agent’s cooperations are
created inside the starting function.
Cooperation is a group of agents which must work
together and can’t exist one without another.
For example: pinger and ponger agents which send
ping/pong messages back and forth. There is no any
sense in pinger agent without ponger agent. They
must appear and disappear at the same time.
SObjectizer Team, Jan 2016
Creation of a cooperation with two agents:
void init( so_5::environment_t & env )
{
auto coop = env.create_coop( so_5::autoname );
coop->make_agent< pinger >();
coop->make_agent< ponger >();
env.register_coop( std::move( coop ) );
}
SObjectizer Team, Jan 2016
void init( so_5::environment_t & env )
{
auto coop = env.create_coop( so_5::autoname );
coop->make_agent< pinger >();
coop->make_agent< ponger >();
env.register_coop( std::move( coop ) );
}
Creation consists of three steps.
At the beginning the Environment
creates a cooperation...
Creation of a cooperation with two agents:
SObjectizer Team, Jan 2016
void init( so_5::environment_t & env )
{
auto coop = env.create_coop( so_5::autoname );
coop->make_agent< pinger >();
coop->make_agent< ponger >();
env.register_coop( std::move( coop ) );
}
Then the cooperation is filled
up with agents...
make_agent() method is like
std::make_unique from
C++14. It creates dynamically
allocated agent of specified
type.
Creation of a cooperation with two agents:
SObjectizer Team, Jan 2016
void init( so_5::environment_t & env )
{
auto coop = env.create_coop( so_5::autoname );
coop->make_agent< pinger >();
coop->make_agent< ponger >();
env.register_coop( std::move( coop ) );
}
Then the cooperation
is being registered.
Creation of a cooperation with two agents:
SObjectizer Team, Jan 2016
void init( so_5::environment_t & env )
{
auto coop = env.create_coop( so_5::autoname );
coop->make_agent< pinger >();
coop->make_agent< ponger >();
env.register_coop( std::move( coop ) );
}
Every cooperation must have unique
name. The uniqueness is checked
inside register_coop().
But SObjectizer can be asked to
generate a name for the new
cooperation automatically.
Creation of a cooperation with two agents:
SObjectizer Team, Jan 2016
void init( so_5::environment_t & env )
{
auto coop = env.create_coop( so_5::autoname );
coop->make_agent< pinger >();
coop->make_agent< ponger >();
env.register_coop( std::move( coop ) );
}
Starting function finishes after cooperation registration.
But the Environment will work until that cooperation will be deregistered.
Or the Environment stop function will be called explicitly.
Creation of a cooperation with two agents:
SObjectizer Team, Jan 2016
What is an agent?
Let’s start with the simplest agent in this example.
A ponger agent.
SObjectizer Team, Jan 2016
It does very simple tasks:
● receives ping messages
● replies with pong messages.
So first of all let’s define those messages...
SObjectizer Team, Jan 2016
Definition of the messages:
struct ping : public so_5::message_t
{
unsigned int m_req;
ping( unsigned int req ) : m_req{ req } {}
};
struct pong : public so_5::message_t
{
unsigned int m_resp;
pong( unsigned int resp ) : m_resp{ resp } {}
};
SObjectizer Team, Jan 2016
struct ping : public so_5::message_t
{
unsigned int m_req;
ping( unsigned int req ) : m_req{ req } {}
};
struct pong : public so_5::message_t
{
unsigned int m_resp;
pong( unsigned int resp ) : m_resp{ resp } {}
};
Every message must be
represented by a separate C++
class (or a structure).
Message dispatching and selection
of a handler are based on the
message type information.
Definition of the messages:
SObjectizer Team, Jan 2016
struct ping : public so_5::message_t
{
unsigned int m_req;
ping( unsigned int req ) : m_req{ req } {}
};
struct pong : public so_5::message_t
{
unsigned int m_resp;
pong( unsigned int resp ) : m_resp{ resp } {}
};
Messages types with some data
inside usually derived from common
base class so_5::message_t. In v.
5.5.15 it is not necessary but
inheritance is shown here just for
demonstration purposes.
There are also messages without
actual data. They are called signals.
They will be described further.
Definition of the messages:
SObjectizer Team, Jan 2016
struct ping : public so_5::message_t
{
unsigned int m_req;
ping( unsigned int req ) : m_req{ req } {}
};
struct pong : public so_5::message_t
{
unsigned int m_resp;
pong( unsigned int resp ) : m_resp{ resp } {}
};
SObjectizer has no significant
limits for message’s content.
In this particular case the m_req
and m_resp fields are
necessary for the sample logic.
They have no relation to
SObjectizer features.
Definition of the messages:
SObjectizer Team, Jan 2016
ponger agent:
class ponger : public so_5::agent_t
{
public :
ponger( context_t ctx )
: so_5::agent_t( ctx )
, m_table( env.create_mbox( "table" ) )
{}
virtual void so_define_agent() override
{
so_subscribe( m_table ).event( &ponger::evt_ping );
}
private :
const so_5::mbox_t m_table;
void evt_ping( const ping & evt )
{
so_5::send< pong >( m_table, evt.m_req );
}
};
SObjectizer Team, Jan 2016
class ponger : public so_5::agent_t
{
public :
ponger( context_t ctx )
: so_5::agent_t( ctx )
, m_table( env.create_mbox( "table" ) )
{}
virtual void so_define_agent() override
{
so_subscribe( m_table ).event( &ponger::evt_ping );
}
private :
const so_5::mbox_t m_table;
void evt_ping( const ping & evt )
{
so_5::send< pong >( m_table, evt.m_req );
}
};
Every ordinary agent must be
represented by a C++ class.
There also can be non ordinary
agents named ad-hoc agents.
They will be described further.
ponger agent:
SObjectizer Team, Jan 2016
class ponger : public so_5::agent_t
{
public :
ponger( context_t ctx )
: so_5::agent_t( ctx )
, m_table( env.create_mbox( "table" ) )
{}
virtual void so_define_agent() override
{
so_subscribe( m_table ).event( &ponger::evt_ping );
}
private :
const so_5::mbox_t m_table;
void evt_ping( const ping & evt )
{
so_5::send< pong >( m_table, evt.m_req );
}
};
Class of ordinary agent must be
derived from common base type
so_5::agent_t.
ponger agent:
SObjectizer Team, Jan 2016
ponger agent:
class ponger : public so_5::agent_t
{
public :
ponger( context_t ctx )
: so_5::agent_t( ctx )
, m_table( env.create_mbox( "table" ) )
{}
virtual void so_define_agent() override
{
so_subscribe( m_table ).event( &ponger::evt_ping );
}
private :
const so_5::mbox_t m_table;
void evt_ping( const ping & evt )
{
so_5::send< pong >( m_table, evt.m_req );
}
};
Every agent must be bound to
an Environment where an
agent will work.
Because of that a reference to
Environment object must be
passed to the agent’s
constructor and redirected to
the constructor of the base
type so_5::agent_t. A
reference to Environment is
inside of context_t object.
SObjectizer Team, Jan 2016
ponger agent:
class ponger : public so_5::agent_t
{
public :
ponger( context_t ctx )
: so_5::agent_t( ctx )
, m_table( env.create_mbox( "table" ) )
{}
virtual void so_define_agent() override
{
so_subscribe( m_table ).event( &ponger::evt_ping );
}
private :
const so_5::mbox_t m_table;
void evt_ping( const ping & evt )
{
so_5::send< pong >( m_table, evt.m_req );
}
};
SObjectizer calls
so_define_agent() method
before an agent will be
registered.
Agent must perform all
necessary tuning actions in
this method. Create
message subscriptions in
particular.
SObjectizer Team, Jan 2016
class ponger : public so_5::agent_t
{
public :
ponger( context_t ctx )
: so_5::agent_t( ctx )
, m_table( env.create_mbox( "table" ) )
{}
virtual void so_define_agent() override
{
so_subscribe( m_table ).event( &ponger::evt_ping );
}
private :
const so_5::mbox_t m_table;
void evt_ping( const ping & evt )
{
so_5::send< pong >( m_table, evt.m_req );
}
};
Ponger agent subscribes only to
one message of ping type. This
message is going from a message
box with name “table”.
Message box must be specified
explicitly. But the message type is
deduced by SObjectizer
automatically from the message
handler signature.
ponger agent:
SObjectizer Team, Jan 2016
class ponger : public so_5::agent_t
{
public :
ponger( context_t ctx )
: so_5::agent_t( ctx )
, m_table( env.create_mbox( "table" ) )
{}
virtual void so_define_agent() override
{
so_subscribe( m_table ).event( &ponger::evt_ping );
}
private :
const so_5::mbox_t m_table;
void evt_ping( const ping & evt )
{
so_5::send< pong >( m_table, evt.m_req );
}
};
A message handler method is named
event handler method. Or just event.
ponger agent:
SObjectizer Team, Jan 2016
class ponger : public so_5::agent_t
{
public :
ponger( context_t ctx )
: so_5::agent_t( ctx )
, m_table( env.create_mbox( "table" ) )
{}
virtual void so_define_agent() override
{
so_subscribe( m_table ).event( &ponger::evt_ping );
}
private :
const so_5::mbox_t m_table;
void evt_ping( const ping & evt )
{
so_5::send< pong >( m_table, evt.m_req );
}
};
A message instance which
caused an event is passed to
event handler by const reference.
Event handler must not modify
that message instance because it
can be handled by the different
agents at the same time.
ponger agent:
SObjectizer Team, Jan 2016
Agent replies by sending a pong
message instance to the message
box with name “table”.
ponger agent:
class ponger : public so_5::agent_t
{
public :
ponger( context_t ctx )
: so_5::agent_t( ctx )
, m_table( env.create_mbox( "table" ) )
{}
virtual void so_define_agent() override
{
so_subscribe( m_table ).event( &ponger::evt_ping );
}
private :
const so_5::mbox_t m_table;
void evt_ping( const ping & evt )
{
so_5::send< pong >( m_table, evt.m_req );
}
};
SObjectizer Team, Jan 2016
class ponger : public so_5::agent_t
{
public :
ponger( context_t ctx )
: so_5::agent_t( ctx )
, m_table( env.create_mbox( "table" ) )
{}
virtual void so_define_agent() override
{
so_subscribe( m_table ).event( &ponger::evt_ping );
}
private :
const so_5::mbox_t m_table;
void evt_ping( const ping & evt )
{
so_5::send< pong >( m_table, evt.m_req );
}
};
so_5::send() template function
constructs an object of pong type
and sends it to the message box
specified.
ponger agent:
SObjectizer Team, Jan 2016
class ponger : public so_5::agent_t
{
public :
ponger( context_t ctx )
: so_5::agent_t( ctx )
, m_table( env.create_mbox( "table" ) )
{}
virtual void so_define_agent() override
{
so_subscribe( m_table ).event( &ponger::evt_ping );
}
private :
const so_5::mbox_t m_table;
void evt_ping( const ping & evt )
{
so_5::send< pong >( m_table, evt.m_req );
}
};
All arguments after message box
are passed to the message object’
s constructor.
In this case it is resp argument for
the pong’s constructor.
ponger agent:
SObjectizer Team, Jan 2016
class ponger : public so_5::agent_t
{
public :
ponger( context_t ctx )
: so_5::agent_t( ctx )
, m_table( env.create_mbox( "table" ) )
{}
virtual void so_define_agent() override
{
so_subscribe( m_table ).event( &ponger::evt_ping );
}
private :
const so_5::mbox_t m_table;
void evt_ping( const ping & evt )
{
so_5::send< pong >( m_table, evt.m_req );
}
};
Ponger agent gets a reference to
the message box for message
exchange by itself.
In this case it is a message box
with name “table”. This box is
created by invocation of
create_mbox(). A reference to
message box is stored inside the
agent.
ponger agent:
SObjectizer Team, Jan 2016
pinger agent (beginning):
class pinger : public so_5::agent_t
{
public :
pinger( context_t ctx )
: so_5::agent_t( ctx )
, m_table( env.create_mbox( "table" ) )
{}
virtual void so_define_agent() override
{
so_subscribe( m_table ).event( &pinger::evt_pong );
}
virtual void so_evt_start() override
{
so_5::send< ping >( m_table, 500 );
}
SObjectizer Team, Jan 2016
class pinger : public so_5::agent_t
{
public :
pinger( context_t ctx )
: so_5::agent_t( ctx )
, m_table( env.create_mbox( "table" ) )
{}
virtual void so_define_agent() override
{
so_subscribe( m_table ).event( &pinger::evt_pong );
}
virtual void so_evt_start() override
{
so_5::send< ping >( m_table, 500 );
}
Pinger agent is very similar to the
ponger agent: receives a
context_t object in its constructor
and creates a reference to
message box with name “table”.
Pinger also subscribes to a single
message in so_define_agent().
pinger agent (beginning):
SObjectizer Team, Jan 2016
class pinger : public so_5::agent_t
{
public :
pinger( context_t ctx )
: so_5::agent_t( ctx )
, m_table( env.create_mbox( "table" ) )
{}
virtual void so_define_agent() override
{
so_subscribe( m_table ).event( &pinger::evt_pong );
}
virtual void so_evt_start() override
{
so_5::send< ping >( m_table, 500 );
}
But there is one significant
distinction: so_evt_start()
method. This method is called
just after successful registration
of the agent’s cooperation. An
agent can perform any starting
actions in that method.
In this particular case: sends the
very first ping message.
pinger agent (beginning):
SObjectizer Team, Jan 2016
pinger agent (ending):
private :
const so_5::mbox_t m_table;
void evt_pong( const pong & evt )
{
if( evt.m_resp )
so_5::send< ping >( m_table, evt.m_resp - 1 );
else
so_deregister_agent_coop_normally();
}
};
SObjectizer Team, Jan 2016
pinger agent (ending):
private :
const so_5::mbox_t m_table;
void evt_pong( const pong & evt )
{
if( evt.m_resp )
so_5::send< ping >( m_table, evt.m_resp - 1 );
else
so_deregister_agent_coop_normally();
}
};
In the evt_pong() the agent can
continue the message exchange
by sending the next ping
message. Or, in the case when all
messages have been sent,
cooperation deregistration can be
initiated.
SObjectizer Team, Jan 2016
pinger agent (ending):
private :
const so_5::mbox_t m_table;
void evt_pong( const pong & evt )
{
if( evt.m_resp )
so_5::send< ping >( m_table, evt.m_resp - 1 );
else
so_deregister_agent_coop_normally();
}
};
The reasons for deregistering a
cooperation might be different. In this
case the deregistration is a normal part
of the application logic.
There will be no live cooperations after
deregistration of pinger/ponger
cooperation. So Environment will finish
its work and so_5::launch will return
control to the caller.
SObjectizer Team, Jan 2016
Few words about message boxes (mboxes)...
Despite other similar tools like Erlang, Akka or CAF,
in SObjectizer a message is sent not to an agent, but
to a message box (mbox).
There could be one agent behind the mbox.
Or many agents.
Or none.
SObjectizer Team, Jan 2016
There are two types of mboxes in SObjectizer:
SObjectizer Team, Jan 2016
Multi-Producers/Multi-Consumers mboxes.
They are like “bulletin boards”. A message sent to
such mbox becomes available for all subscribers
of the mbox. MPMC-mbox is shown in the code
above.
SObjectizer Team, Jan 2016
Multi-Producers/Single-Consumer mboxes.
Mboxes of that type have only one subscriber. It
is an agent who owns such mbox.
SObjectizer Team, Jan 2016
Lets add another agent to the example to show
specifics of MPMC-mboxes...
This agent will listen the message exchange
between pinger and ponger agents, and will count
the messages sent.
SObjectizer Team, Jan 2016
listener agent:
class listener : public so_5::agent_t
{
public :
listener( context_t ctx )
: so_5::agent_t( ctx )
, m_table( env.create_mbox( "table" ) )
{}
virtual void so_define_agent() override {
so_subscribe( m_table )
.event( [this]( const ping & ) { ++m_pings; } )
.event( [this]( const pong & ) { ++m_pongs; } );
}
virtual void so_evt_finish() override {
std::cout << "result: " << m_pings << "/" << m_pongs << std::endl;
}
private :
const so_5::mbox_t m_table;
unsigned int m_pings = 0;
unsigned int m_pongs = 0;
};
SObjectizer Team, Jan 2016
listener agent:
class listener : public so_5::agent_t
{
public :
listener( context_t ctx )
: so_5::agent_t( ctx )
, m_table( env.create_mbox( "table" ) )
{}
virtual void so_define_agent() override {
so_subscribe( m_table )
.event( [this]( const ping & ) { ++m_pings; } )
.event( [this]( const pong & ) { ++m_pongs; } );
}
virtual void so_evt_finish() override {
std::cout << "result: " << m_pings << "/" << m_pongs << std::endl;
}
private :
const so_5::mbox_t m_table;
unsigned int m_pings = 0;
unsigned int m_pongs = 0;
};
It is necessary to receive two
messages. Because of that the
agent subscribes two events.
Lambda-functions are used
instead of event handler
methods. Types of messages
are automatically deduced from
lambdas signatures.
SObjectizer Team, Jan 2016
listener agent:
class listener : public so_5::agent_t
{
public :
listener( context_t ctx )
: so_5::agent_t( ctx )
, m_table( env.create_mbox( "table" ) )
{}
virtual void so_define_agent() override {
so_subscribe( m_table )
.event( [this]( const ping & ) { ++m_pings; } )
.event( [this]( const pong & ) { ++m_pongs; } );
}
virtual void so_evt_finish() override {
std::cout << "result: " << m_pings << "/" << m_pongs << std::endl;
}
private :
const so_5::mbox_t m_table;
unsigned int m_pings = 0;
unsigned int m_pongs = 0;
};
so_evt_finish() method is the
opposite to so_evt_start(). It is
called for agent just before the very
end of agent’s work. In this case
that method is used for result
printing.
SObjectizer Team, Jan 2016
If we add a listener to the cooperation:
void init( so_5::environment_t & env )
{
auto coop = env.create_coop( so_5::autoname );
coop->make_agent< pinger >();
coop->make_agent< ponger >();
coop->make_agent< listener >();
env.register_coop( std::move( coop ) );
}
SObjectizer Team, Jan 2016
Then we will see at the end:
result: 501/501
It means that message sending to MPMC-mbox is
a broadcast message sending.
SObjectizer Team, Jan 2016
MPMC-mboxes must be created manually.
MPSC-mboxes, in contradiction, are created
automatically for every agent.
It means that every agent has its own MPSC-mbox.
In SObjectizer's terms such mbox is often named
direct_mbox.
SObjectizer Team, Jan 2016
When a message is sent to MPSC-mbox it will go
to mbox owner for processing. Or just discarded if
mbox owner is not subscribed to that message.
It means that if two agents interact via
direct_mboxes nobody can listen them.
SObjectizer Team, Jan 2016
But direct_mboxes are used not for creation of a
“private channels” for message exchanges.
Direct_mboxes are more efficient than MPMC-
mboxes. Dispatching for direct_mboxes is simpler
and requires fewer internal locks.
Therefore usage of direct_mboxes is more preferable
if application logic doesn’t require broadcast message
sending.
SObjectizer Team, Jan 2016
There is no need in broadcast message sending
in the example above.
Lets rewrite it with direct_mboxes.
And throw out a listener agent. Lets pinger and
ponger agent count the messages by themselves.
And replace messages with signals.
SObjectizer Team, Jan 2016
A signal is a special case of a message when
only the fact of the message existence is
important.
But the message itself has no any data inside.
It is like sending of atoms in Erlang, when only an
atom is sent without any additional data.
SObjectizer Team, Jan 2016
In the application code written with SObjectizer
signals are so widely used that SObjectizer’s API
was extended to simplify usage of signals.
At the API level the work with signal is very similar
to the work with messages. Sometimes.
Sometimes not.
SObjectizer Team, Jan 2016
Replace ping and pong messages with signals...
SObjectizer Team, Jan 2016
Replace ping and pong messages with signals...
SObjectizer Team, Jan 2016
struct ping : public so_5::message_t
{
unsigned int m_req;
ping( unsigned int req ) : m_req{ req } {}
};
struct pong : public so_5::message_t
{
unsigned int m_resp;
pong( unsigned int resp ) : m_resp{ resp } {}
};
struct ping : public so_5::signal_t {};
struct pong : public so_5::signal_t {};
Replace ping and pong messages with signals...
SObjectizer Team, Jan 2016
struct ping : public so_5::message_t
{
unsigned int m_req;
ping( unsigned int req ) : m_req{ req } {}
};
struct pong : public so_5::message_t
{
unsigned int m_resp;
pong( unsigned int resp ) : m_resp{ resp } {}
};
struct ping : public so_5::signal_t {};
struct pong : public so_5::signal_t {};
Signal types must be derived from so_5::signal_t
and must not contain any data inside.
Changing of pinger agent (beginning):
class pinger : public so_5::agent_t
{
public :
pinger( context_t ctx )
: so_5::agent_t( ctx )
{}
void set_ponger_mbox( const so_5::mbox_t & mbox ) {
m_ponger = mbox;
}
virtual void so_define_agent() override {
so_subscribe_self().event< pong >(
[this]{
++m_pongs;
so_5::send< ping >( m_ponger );
} );
}
SObjectizer Team, Jan 2016
Changing of pinger agent (beginning):
class pinger : public so_5::agent_t
{
public :
pinger( context_t ctx )
: so_5::agent_t( ctx )
{}
void set_ponger_mbox( const so_5::mbox_t & mbox ) {
m_ponger = mbox;
}
virtual void so_define_agent() override {
so_subscribe_self().event< pong >(
[this]{
++m_pongs;
so_5::send< ping >( m_ponger );
} );
}
A direct_mbox can be accessed
only after the agent creation.
Because of that a separate method
is needed for connecting of pinger
and ponger agents. It will be called
after instantiation of the agent.
SObjectizer Team, Jan 2016
Changing of pinger agent (beginning):
class pinger : public so_5::agent_t
{
public :
pinger( context_t ctx )
: so_5::agent_t( ctx )
{}
void set_ponger_mbox( const so_5::mbox_t & mbox ) {
m_ponger = mbox;
}
virtual void so_define_agent() override {
so_subscribe_self().event< pong >(
[this]{
++m_pongs;
so_5::send< ping >( m_ponger );
} );
}
so_subscribe_self() method is used
for subscription to message from
agent's direct_mbox.
Method event receives a lambda-
function with reaction to pong signal.
SObjectizer Team, Jan 2016
Changing of pinger agent (beginning):
class pinger : public so_5::agent_t
{
public :
pinger( context_t ctx )
: so_5::agent_t( ctx )
{}
void set_ponger_mbox( const so_5::mbox_t & mbox ) {
m_ponger = mbox;
}
virtual void so_define_agent() override {
so_subscribe_self().event< pong >(
[this]{
++m_pongs;
so_5::send< ping >( m_ponger );
} );
}
The signal type must be explicitly
specified during subscription. A
method or lambda-function without
argument can only be used as
signal handler. Unlike a message
there is no a signal instance to be
passed to a handler. Because of
that there is no way to deduce
signal type by the event handler’s
signature.
SObjectizer Team, Jan 2016
Changing of pinger agent (ending):
virtual void so_evt_start() override {
so_5::send< ping >( m_ponger );
}
virtual void so_evt_finish() override {
std::cout << "pongs: " << m_pongs << std::endl;
}
private :
so_5::mbox_t m_ponger;
unsigned int m_pongs = 0;
};
SObjectizer Team, Jan 2016
Changing of pinger agent (ending):
virtual void so_evt_start() override {
so_5::send< ping >( m_ponger );
}
virtual void so_evt_finish() override {
std::cout << "pongs: " << m_pongs << std::endl;
}
private :
so_5::mbox_t m_ponger;
unsigned int m_pongs = 0;
};
Signal sending is performed by the
same so_5::send() function. Like a
message sending. But there is no
any other arguments after receiver
mbox.
SObjectizer Team, Jan 2016
Similar changes to a ponger agent (beginning):
class ponger : public so_5::agent_t
{
public :
ponger( context_t ctx )
: so_5::agent_t( ctx)
{}
void set_pinger_mbox( const so_5::mbox_t & mbox ) {
m_pinger = mbox;
}
virtual void so_define_agent() override {
so_subscribe_self().event< ping >(
[this]{
++m_pings;
so_5::send< pong >( m_pinger );
} );
}
SObjectizer Team, Jan 2016
Similar changes to a ponger agent (ending):
virtual void so_evt_finish() override {
std::cout << "pings: " << m_pings << std::endl;
}
private :
so_5::mbox_t m_pinger;
unsigned int m_pings = 0;
};
SObjectizer Team, Jan 2016
Creation of the cooperation becomes more verbose:
void init( so_5::environment_t & env )
{
auto coop = env.create_coop( so_5::autoname );
auto a_pinger = coop->make_agent< pinger >();
auto a_ponger = coop->make_agent< ponger >();
a_pinger->set_ponger_mbox( a_ponger->so_direct_mbox() );
a_ponger->set_pinger_mbox( a_pinger->so_direct_mbox() );
env.register_coop( std::move( coop ) );
}
SObjectizer Team, Jan 2016
Moreover there is an error...
SObjectizer Team, Jan 2016
No one stops them!
They will ping each other infinitely.
SObjectizer Team, Jan 2016
Fix this problem by adding another agent that will
stop example after one second...
SObjectizer Team, Jan 2016
Because this agent will handle only one event
there is no need to define a separate class for it,
redefine so_define_agent() method and so on...
An ad-hoc agent will be used instead.
SObjectizer Team, Jan 2016
Ad-hoc agent for stopping the work after one
second:
struct stop : public so_5::signal_t {};
auto stopper = coop->define_agent();
stopper.event< stop >( stopper, [&env]{ env.stop(); } );
SObjectizer Team, Jan 2016
Ad-hoc agent for stopping the work after one
second:
struct stop : public so_5::signal_t {};
auto stopper = coop->define_agent();
stopper.event< stop >( stopper, [&env]{ env.stop(); } );
Stop signal.
SObjectizer Team, Jan 2016
Ad-hoc agent for stopping the work after one
second:
struct stop : public so_5::signal_t {};
auto stopper = coop->define_agent();
stopper.event< stop >( stopper, [&env]{ env.stop(); } );
Ad-hoc agent creation.
A handle is returned. This handle
can be used for agent tuning.
SObjectizer Team, Jan 2016
Ad-hoc agent for stopping the work after one
second:
struct stop : public so_5::signal_t {};
auto stopper = coop->define_agent();
stopper.event< stop >( stopper, [&env]{ env.stop(); } );
The new agent is subscribed to just
one signal.
SObjectizer Team, Jan 2016
Ad-hoc agent for stopping the work after one
second:
struct stop : public so_5::signal_t {};
auto stopper = coop->define_agent();
stopper.event< stop >( stopper, [&env]{ env.stop(); } );
Signal is expected from direct_mbox
of the the agent.
SObjectizer Team, Jan 2016
Ad-hoc agent for stopping the work after one
second:
struct stop : public so_5::signal_t {};
auto stopper = coop->define_agent();
stopper.event< stop >( stopper, [&env]{ env.stop(); } );
The signal handler will stop
SObjectizer Environment.
The single cooperation will be
deregistered automatically.
SObjectizer Team, Jan 2016
Ad-hoc agent is created and tuned.
A delayed for one second stop signal must be sent:
env.register_coop( std::move( coop ) );
so_5::send_delayed< stop >( stopper, std::chrono::seconds(1) );
SObjectizer Team, Jan 2016
Ad-hoc agent is created and tuned.
A delayed for one second stop signal must be sent:
env.register_coop( std::move( coop ) );
so_5::send_delayed< stop >( stopper, std::chrono::seconds(1) );
A so_5::send_delayed function
make delayed send of a signal or a
message.
In this case a stop signal will be
sent to the direct_mbox of the new
ad-hoc agent with one second
delay.
SObjectizer Team, Jan 2016
Finally the starting function becomes:
void init( so_5::environment_t & env )
{
auto coop = env.create_coop( so_5::autoname );
auto a_pinger = coop->make_agent< pinger >();
auto a_ponger = coop->make_agent< ponger >();
a_pinger->set_ponger_mbox( a_ponger->so_direct_mbox() );
a_ponger->set_pinger_mbox( a_pinger->so_direct_mbox() );
struct stop : public so_5::signal_t {};
auto stopper = coop->define_agent();
stopper.event< stop >( stopper, [&env]{ env.stop(); } );
env.register_coop( std::move( coop ) );
so_5::send_delayed< stop >( stopper, std::chrono::seconds(1) );
}
SObjectizer Team, Jan 2016
Running the updated example...
pongs: 4441168
pings: 4441169
SObjectizer Team, Jan 2016
Just above 8M messages per seconds.
Core i7 2.4GHz, 8GiB RAM, Win8.1 64-bit,
Visual C++ 13.0 64-bit.
SObjectizer Team, Jan 2016
So far, so good. But which working context has
been used?
SObjectizer Team, Jan 2016
All agents were working on a single thread!
This example just shows the effectiveness of
message passing between agents which are
working on the same context.
But who choose the context?
And how an agent can be bound to another
context?
SObjectizer Team, Jan 2016
A programmer makes choice of context when
binds an agent to a dispatcher.
If dispatcher is not specified then an agent will be
bound to default dispatcher.
Just like in the example above.
SObjectizer Team, Jan 2016
The default dispatcher runs all the agents on a
single working thread.
There is a something like “cooperative
multitasking” for agents on the default dispatcher.
If one of them will slow down the other will slow
down too.
But it is possible to create any number of various
dispatchers and bind agents to the them.
SObjectizer Team, Jan 2016
Lets bind pinger and ponger agent to different
working threads (every agent will have its own
dedicated working thread)...
An instance of active_obj dispatcher will be
created for that. Agents will be bound to it.
This dispatcher creates a dedicated thread for
each agent bound to it (an agent becomes an
active object).
SObjectizer Team, Jan 2016
There is nothing to change inside the agents...
All the changes will be in the starting function
only.
SObjectizer Team, Jan 2016
Binding of the agents to different dispatches:
void init( so_5::environment_t & env )
{
auto coop = env.create_coop( so_5::autoname,
so_5::disp::active_obj::create_private_disp( env )->binder() );
auto a_pinger = coop->make_agent< pinger >();
auto a_ponger = coop->make_agent< ponger >();
a_pinger->set_ponger_mbox( a_ponger->so_direct_mbox() );
a_ponger->set_pinger_mbox( a_pinger->so_direct_mbox() );
struct stop : public so_5::signal_t {};
auto stopper = coop->define_agent( so_5::create_default_disp_binder() );
stopper.event< stop >( stopper, [&env]{ env.stop(); } );
env.register_coop( std::move( coop ) );
so_5::send_delayed< stop >( env, stopper, std::chrono::seconds(1) );
}
SObjectizer Team, Jan 2016
Binding of the agents to different dispatches:
void init( so_5::environment_t & env )
{
auto coop = env.create_coop( so_5::autoname,
so_5::disp::active_obj::create_private_disp( env )->binder() );
auto a_pinger = coop->make_agent< pinger >();
auto a_ponger = coop->make_agent< ponger >();
a_pinger->set_ponger_mbox( a_ponger->so_direct_mbox() );
a_ponger->set_pinger_mbox( a_pinger->so_direct_mbox() );
struct stop : public so_5::signal_t {};
auto stopper = coop->define_agent( so_5::create_default_disp_binder() );
stopper.event< stop >( stopper, [&env]{ env.stop(); } );
env.register_coop( std::move( coop ) );
so_5::send_delayed< stop >( env, stopper, std::chrono::seconds(1) );
}
Creation of the active objects
dispatcher. A binder for that
dispatcher will be used as
main dispatcher binder for the
new coop.
SObjectizer Team, Jan 2016
Binding of the agents to different dispatches:
void init( so_5::environment_t & env )
{
auto coop = env.create_coop( so_5::autoname,
so_5::disp::active_obj::create_private_disp( env )->binder() );
auto a_pinger = coop->make_agent< pinger >();
auto a_ponger = coop->make_agent< ponger >();
a_pinger->set_ponger_mbox( a_ponger->so_direct_mbox() );
a_ponger->set_pinger_mbox( a_pinger->so_direct_mbox() );
struct stop : public so_5::signal_t {};
auto stopper = coop->define_agent( so_5::create_default_disp_binder() );
stopper.event< stop >( stopper, [&env]{ env.stop(); } );
env.register_coop( std::move( coop ) );
so_5::send_delayed< stop >( env, stopper, std::chrono::seconds(1) );
}
Pinger and ponger agents
are being added to the
cooperation without any
additional information. It
means they will be bound to
the main cooperation
dispatcher. It is the
active_obj dispatcher created
above.
SObjectizer Team, Jan 2016
Binding of the agents to different dispatches:
void init( so_5::environment_t & env )
{
auto coop = env.create_coop( so_5::autoname,
so_5::disp::active_obj::create_private_disp( env )->binder() );
auto a_pinger = coop->make_agent< pinger >();
auto a_ponger = coop->make_agent< ponger >();
a_pinger->set_ponger_mbox( a_ponger->so_direct_mbox() );
a_ponger->set_pinger_mbox( a_pinger->so_direct_mbox() );
struct stop : public so_5::signal_t {};
auto stopper = coop->define_agent( so_5::create_default_disp_binder() );
stopper.event< stop >( stopper, [&env]{ env.stop(); } );
env.register_coop( std::move( coop ) );
so_5::send_delayed< stop >( env, stopper, std::chrono::seconds(1) );
}
But there is no need for a separate thread
for stopper agent. Because of that this
agent is being bound to the default
dispatcher explicitly. Without this the
stopper will be bound to the cooperation
main dispatcher.
SObjectizer Team, Jan 2016
What we get now?
SObjectizer Team, Jan 2016
What we get now?
pings: pongs: 1234623
1234624
SObjectizer Team, Jan 2016
Is it ok?
SObjectizer Team, Jan 2016
Yes. It is.
And there could be more strange results.
But what happened?
SObjectizer Team, Jan 2016
Pinger and ponger agents are now working on
different threads and compete for std::cout object.
As result the output to std::cout got mixed. It could
be even worse. Or could not be mixed at all.
This is concurrency in action...
SObjectizer Team, Jan 2016
pings: pongs: 1234623
1234624
What else?
SObjectizer Team, Jan 2016
The performance has dropped. We have seen 8M
messages per second on one thread. And just 2M
on two threads.
It is expected result. Passing a single message
from thread to thread is an expensive operation.
SObjectizer Team, Jan 2016
But is there any changes in the agents?
SObjectizer Team, Jan 2016
Ponger agent for one thread:
class ponger : public so_5::agent_t
{
public :
ponger( context_t ctx )
: so_5::agent_t( ctx )
{}
void set_pinger_mbox( const so_5::mbox_t & mbox ) {
m_pinger = mbox;
}
virtual void so_define_agent() override {
so_subscribe_self().event< ping >(
[this]{
++m_pings;
so_5::send< pong >( m_pinger );
} );
}
virtual void so_evt_finish() override {
std::cout << "pings: " << m_pings << std::endl;
}
private :
so_5::mbox_t m_pinger;
unsigned int m_pings = 0;
};
SObjectizer Team, Jan 2016
class ponger : public so_5::agent_t
{
public :
ponger( context_t ctx )
: so_5::agent_t( ctx )
{}
void set_pinger_mbox( const so_5::mbox_t & mbox ) {
m_pinger = mbox;
}
virtual void so_define_agent() override {
so_subscribe_self().event< ping >(
[this]{
++m_pings;
so_5::send< pong >( m_pinger );
} );
}
virtual void so_evt_finish() override {
std::cout << "pings: " << m_pings << std::endl;
}
private :
so_5::mbox_t m_pinger;
unsigned int m_pings = 0;
};
Ponger agent for two threads:
class ponger : public so_5::agent_t
{
public :
ponger( context_t ctx )
: so_5::agent_t( ctx )
{}
void set_pinger_mbox( const so_5::mbox_t & mbox ) {
m_pinger = mbox;
}
virtual void so_define_agent() override {
so_subscribe_self().event< ping >(
[this]{
++m_pings;
so_5::send< pong >( m_pinger );
} );
}
virtual void so_evt_finish() override {
std::cout << "pings: " << m_pings << std::endl;
}
private :
so_5::mbox_t m_pinger;
unsigned int m_pings = 0;
};
SObjectizer Team, Jan 2016
Ponger agent for one thread:
It is a direct consequence of interaction only by
asynchronous messages.
Because of that agents are unaware about
working context.
Providing an appropriate set of different
dispatchers is a task of SObjectizer.
SObjectizer Team, Jan 2016
SObjectizer has several ready-to-use dispatchers.
There are one_thread, active_obj, active_group,
thread_pool, adv_thread_pool and three more
dispatchers which support priorities of agents...
SObjectizer Team, Jan 2016
A programmer can not only select the appropriate
type of a dispatcher...
...but can create any number of those dispatchers.
SObjectizer Team, Jan 2016
For example:
● one one_thread dispatcher for AMQP-client agent;
● one thread_pool dispatcher for handling requests from
AMQP-queues;
● one active_obj dispatcher for DBMS-related agents;
● yet another active_obj dispatcher for agents whose work
with HSMs connected to the computer;
● and yet another thread_pool dispatcher for agents for
managing all the stuff described above.
SObjectizer Team, Jan 2016
But there are yet more SObjectizer features...
Such important things like:
● agent’s states
● periodic messages
● synchronous agents interaction
● child cooperation
● exception handling
● Run-Time parameters tuning and so on...
SObjectizer Team, Jan 2016
...will be described in a more deep dive
But introductory part is finished.
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

Mais conteúdo relacionado

Mais procurados

Discover Quarkus and GraalVM
Discover Quarkus and GraalVMDiscover Quarkus and GraalVM
Discover Quarkus and GraalVMRomain Schlick
 
C#の強み、或いは何故PHPから乗り換えるのか
C#の強み、或いは何故PHPから乗り換えるのかC#の強み、或いは何故PHPから乗り換えるのか
C#の強み、或いは何故PHPから乗り換えるのかYoshifumi Kawai
 
ラムダ計算入門
ラムダ計算入門ラムダ計算入門
ラムダ計算入門Eita Sugimoto
 
Pertで見積もりを考える
Pertで見積もりを考えるPertで見積もりを考える
Pertで見積もりを考えるYoichi Toyota
 
전형규, SilvervineUE4Lua: UE4에서 Lua 사용하기, NDC2019
전형규, SilvervineUE4Lua: UE4에서 Lua 사용하기, NDC2019전형규, SilvervineUE4Lua: UE4에서 Lua 사용하기, NDC2019
전형규, SilvervineUE4Lua: UE4에서 Lua 사용하기, NDC2019devCAT Studio, NEXON
 
Haskell Day2012 - 参照透過性とは何だったのか
Haskell Day2012 - 参照透過性とは何だったのかHaskell Day2012 - 参照透過性とは何だったのか
Haskell Day2012 - 参照透過性とは何だったのかKousuke Ruichi
 
[델리만주] 대학원 캐슬 - 석사에서 게임 프로그래머까지
[델리만주] 대학원 캐슬 - 석사에서 게임 프로그래머까지[델리만주] 대학원 캐슬 - 석사에서 게임 프로그래머까지
[델리만주] 대학원 캐슬 - 석사에서 게임 프로그래머까지Chris Ohk
 
Functional programming
Functional programmingFunctional programming
Functional programmingijcd
 
Intrinsic Methods in HotSpot VM
Intrinsic Methods in HotSpot VMIntrinsic Methods in HotSpot VM
Intrinsic Methods in HotSpot VMKris Mok
 
Functional Reactive Programming with RxJS
Functional Reactive Programming with RxJSFunctional Reactive Programming with RxJS
Functional Reactive Programming with RxJSstefanmayer13
 
Ksug2015 - JPA3, JPA 내부구조
Ksug2015 - JPA3, JPA 내부구조Ksug2015 - JPA3, JPA 내부구조
Ksug2015 - JPA3, JPA 내부구조Younghan Kim
 
Spring3.1概要 データアクセスとトランザクション処理
Spring3.1概要 データアクセスとトランザクション処理Spring3.1概要 データアクセスとトランザクション処理
Spring3.1概要 データアクセスとトランザクション処理土岐 孝平
 
オブジェクト指向プログラミング入門 -- Java object-oriented programming primer
オブジェクト指向プログラミング入門 -- Java object-oriented programming primerオブジェクト指向プログラミング入門 -- Java object-oriented programming primer
オブジェクト指向プログラミング入門 -- Java object-oriented programming primer増田 亨
 
Domain Modeling Made Functional (DevTernity 2022)
Domain Modeling Made Functional (DevTernity 2022)Domain Modeling Made Functional (DevTernity 2022)
Domain Modeling Made Functional (DevTernity 2022)Scott Wlaschin
 
Advanced Javascript
Advanced JavascriptAdvanced Javascript
Advanced JavascriptAdieu
 
F#の基礎(嘘)
F#の基礎(嘘)F#の基礎(嘘)
F#の基礎(嘘)bleis tift
 

Mais procurados (20)

Discover Quarkus and GraalVM
Discover Quarkus and GraalVMDiscover Quarkus and GraalVM
Discover Quarkus and GraalVM
 
C#の強み、或いは何故PHPから乗り換えるのか
C#の強み、或いは何故PHPから乗り換えるのかC#の強み、或いは何故PHPから乗り換えるのか
C#の強み、或いは何故PHPから乗り換えるのか
 
ラムダ計算入門
ラムダ計算入門ラムダ計算入門
ラムダ計算入門
 
Pertで見積もりを考える
Pertで見積もりを考えるPertで見積もりを考える
Pertで見積もりを考える
 
Identifier
IdentifierIdentifier
Identifier
 
전형규, SilvervineUE4Lua: UE4에서 Lua 사용하기, NDC2019
전형규, SilvervineUE4Lua: UE4에서 Lua 사용하기, NDC2019전형규, SilvervineUE4Lua: UE4에서 Lua 사용하기, NDC2019
전형규, SilvervineUE4Lua: UE4에서 Lua 사용하기, NDC2019
 
Haskell Day2012 - 参照透過性とは何だったのか
Haskell Day2012 - 参照透過性とは何だったのかHaskell Day2012 - 参照透過性とは何だったのか
Haskell Day2012 - 参照透過性とは何だったのか
 
[델리만주] 대학원 캐슬 - 석사에서 게임 프로그래머까지
[델리만주] 대학원 캐슬 - 석사에서 게임 프로그래머까지[델리만주] 대학원 캐슬 - 석사에서 게임 프로그래머까지
[델리만주] 대학원 캐슬 - 석사에서 게임 프로그래머까지
 
Functional programming
Functional programmingFunctional programming
Functional programming
 
Intrinsic Methods in HotSpot VM
Intrinsic Methods in HotSpot VMIntrinsic Methods in HotSpot VM
Intrinsic Methods in HotSpot VM
 
FizzBuzzで学ぶJavaの進化
FizzBuzzで学ぶJavaの進化FizzBuzzで学ぶJavaの進化
FizzBuzzで学ぶJavaの進化
 
Functional Reactive Programming with RxJS
Functional Reactive Programming with RxJSFunctional Reactive Programming with RxJS
Functional Reactive Programming with RxJS
 
Ksug2015 - JPA3, JPA 내부구조
Ksug2015 - JPA3, JPA 내부구조Ksug2015 - JPA3, JPA 내부구조
Ksug2015 - JPA3, JPA 내부구조
 
Spring3.1概要 データアクセスとトランザクション処理
Spring3.1概要 データアクセスとトランザクション処理Spring3.1概要 データアクセスとトランザクション処理
Spring3.1概要 データアクセスとトランザクション処理
 
オブジェクト指向プログラミング入門 -- Java object-oriented programming primer
オブジェクト指向プログラミング入門 -- Java object-oriented programming primerオブジェクト指向プログラミング入門 -- Java object-oriented programming primer
オブジェクト指向プログラミング入門 -- Java object-oriented programming primer
 
PHP FUNCTIONS
PHP FUNCTIONSPHP FUNCTIONS
PHP FUNCTIONS
 
Domain Modeling Made Functional (DevTernity 2022)
Domain Modeling Made Functional (DevTernity 2022)Domain Modeling Made Functional (DevTernity 2022)
Domain Modeling Made Functional (DevTernity 2022)
 
Advanced Javascript
Advanced JavascriptAdvanced Javascript
Advanced Javascript
 
Atomic Architecture
Atomic ArchitectureAtomic Architecture
Atomic Architecture
 
F#の基礎(嘘)
F#の基礎(嘘)F#の基礎(嘘)
F#の基礎(嘘)
 

Destaque

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
 
Dive into SObjectizer-5.5. Sixth part: Synchronous Interaction
Dive into SObjectizer-5.5. Sixth part: Synchronous InteractionDive into SObjectizer-5.5. Sixth part: Synchronous Interaction
Dive into SObjectizer-5.5. Sixth part: Synchronous InteractionYauheni Akhotnikau
 
Dive into SObjectizer 5.5. Third part. Coops
Dive into SObjectizer 5.5. Third part. CoopsDive into SObjectizer 5.5. Third part. Coops
Dive into SObjectizer 5.5. Third part. CoopsYauheni Akhotnikau
 
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
 
Dive into SObjectizer 5.5. Fifth part: Timers
Dive into SObjectizer 5.5. Fifth part: TimersDive into SObjectizer 5.5. Fifth part: Timers
Dive into SObjectizer 5.5. Fifth part: TimersYauheni Akhotnikau
 
Dive into SObjectizer 5.5. Fourth part. Exception
Dive into SObjectizer 5.5. Fourth part. ExceptionDive into SObjectizer 5.5. Fourth part. Exception
Dive into SObjectizer 5.5. Fourth part. ExceptionYauheni Akhotnikau
 
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
 
Dive into SObjectizer 5.5. Seventh part: Message Limits
Dive into SObjectizer 5.5. Seventh part: Message LimitsDive into SObjectizer 5.5. Seventh part: Message Limits
Dive into SObjectizer 5.5. Seventh part: Message LimitsYauheni Akhotnikau
 
Dive into SObjectizer 5.5. Eighth Part: Dispatchers
Dive into SObjectizer 5.5. Eighth Part: DispatchersDive into SObjectizer 5.5. Eighth Part: Dispatchers
Dive into SObjectizer 5.5. Eighth Part: DispatchersYauheni Akhotnikau
 
Evgeniy Muralev, Mark Vince, Working with the compiler, not against it
Evgeniy Muralev, Mark Vince, Working with the compiler, not against itEvgeniy Muralev, Mark Vince, Working with the compiler, not against it
Evgeniy Muralev, Mark Vince, Working with the compiler, not against itSergey Platonov
 
Что и почему писать на Erlang
Что и почему писать на ErlangЧто и почему писать на Erlang
Что и почему писать на ErlangMax Lapshin
 
C++ Core Guidelines
C++ Core Guidelines C++ Core Guidelines
C++ Core Guidelines Sergey Zubkov
 

Destaque (13)

What is SObjectizer 5.5
What is SObjectizer 5.5What is SObjectizer 5.5
What is SObjectizer 5.5
 
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?
 
Dive into SObjectizer-5.5. Sixth part: Synchronous Interaction
Dive into SObjectizer-5.5. Sixth part: Synchronous InteractionDive into SObjectizer-5.5. Sixth part: Synchronous Interaction
Dive into SObjectizer-5.5. Sixth part: Synchronous Interaction
 
Dive into SObjectizer 5.5. Third part. Coops
Dive into SObjectizer 5.5. Third part. CoopsDive into SObjectizer 5.5. Third part. Coops
Dive into SObjectizer 5.5. Third part. Coops
 
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
 
Dive into SObjectizer 5.5. Fifth part: Timers
Dive into SObjectizer 5.5. Fifth part: TimersDive into SObjectizer 5.5. Fifth part: Timers
Dive into SObjectizer 5.5. Fifth part: Timers
 
Dive into SObjectizer 5.5. Fourth part. Exception
Dive into SObjectizer 5.5. Fourth part. ExceptionDive into SObjectizer 5.5. Fourth part. Exception
Dive into SObjectizer 5.5. Fourth part. Exception
 
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
 
Dive into SObjectizer 5.5. Seventh part: Message Limits
Dive into SObjectizer 5.5. Seventh part: Message LimitsDive into SObjectizer 5.5. Seventh part: Message Limits
Dive into SObjectizer 5.5. Seventh part: Message Limits
 
Dive into SObjectizer 5.5. Eighth Part: Dispatchers
Dive into SObjectizer 5.5. Eighth Part: DispatchersDive into SObjectizer 5.5. Eighth Part: Dispatchers
Dive into SObjectizer 5.5. Eighth Part: Dispatchers
 
Evgeniy Muralev, Mark Vince, Working with the compiler, not against it
Evgeniy Muralev, Mark Vince, Working with the compiler, not against itEvgeniy Muralev, Mark Vince, Working with the compiler, not against it
Evgeniy Muralev, Mark Vince, Working with the compiler, not against it
 
Что и почему писать на Erlang
Что и почему писать на ErlangЧто и почему писать на Erlang
Что и почему писать на Erlang
 
C++ Core Guidelines
C++ Core Guidelines C++ Core Guidelines
C++ Core Guidelines
 

Semelhante a Dive into SObjectizer 5.5. Introductory part

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
 
React Native custom components
React Native custom componentsReact Native custom components
React Native custom componentsJeremy Grancher
 
Analysis of merge requests in GitLab using PVS-Studio for C#
Analysis of merge requests in GitLab using PVS-Studio for C#Analysis of merge requests in GitLab using PVS-Studio for C#
Analysis of merge requests in GitLab using PVS-Studio for C#Andrey Karpov
 
PVS-Studio and Continuous Integration: TeamCity. Analysis of the Open RollerC...
PVS-Studio and Continuous Integration: TeamCity. Analysis of the Open RollerC...PVS-Studio and Continuous Integration: TeamCity. Analysis of the Open RollerC...
PVS-Studio and Continuous Integration: TeamCity. Analysis of the Open RollerC...Andrey Karpov
 
Full Stack React Workshop [CSSC x GDSC]
Full Stack React Workshop [CSSC x GDSC]Full Stack React Workshop [CSSC x GDSC]
Full Stack React Workshop [CSSC x GDSC]GDSC UofT Mississauga
 
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
 
React Basic and Advance || React Basic
React Basic and Advance   || React BasicReact Basic and Advance   || React Basic
React Basic and Advance || React Basicrafaqathussainc077
 
Diving into VS 2015 Day2
Diving into VS 2015 Day2Diving into VS 2015 Day2
Diving into VS 2015 Day2Akhil Mittal
 
3 Ways to Get Started with a React App in 2024.pdf
3 Ways to Get Started with a React App in 2024.pdf3 Ways to Get Started with a React App in 2024.pdf
3 Ways to Get Started with a React App in 2024.pdfBOSC Tech Labs
 
Create a meteor chat app in 30 minutes
Create a meteor chat app in 30 minutesCreate a meteor chat app in 30 minutes
Create a meteor chat app in 30 minutesDesignveloper
 
Reactive programming with tracker
Reactive programming with trackerReactive programming with tracker
Reactive programming with trackerDesignveloper
 
Errors that static code analysis does not find because it is not used
Errors that static code analysis does not find because it is not usedErrors that static code analysis does not find because it is not used
Errors that static code analysis does not find because it is not usedAndrey Karpov
 
Basic iOS Training with SWIFT - Part 4
Basic iOS Training with SWIFT - Part 4Basic iOS Training with SWIFT - Part 4
Basic iOS Training with SWIFT - Part 4Manoj Ellappan
 
Analysis of bugs in Orchard CMS
Analysis of bugs in Orchard CMSAnalysis of bugs in Orchard CMS
Analysis of bugs in Orchard CMSPVS-Studio
 
Angular Optimization Web Performance Meetup
Angular Optimization Web Performance MeetupAngular Optimization Web Performance Meetup
Angular Optimization Web Performance MeetupDavid Barreto
 
No sql injection in meteor.js application
No sql injection in meteor.js applicationNo sql injection in meteor.js application
No sql injection in meteor.js applicationDesignveloper
 
M365 global developer bootcamp 2019 Intro to SPFx Version
M365 global developer bootcamp 2019 Intro to SPFx VersionM365 global developer bootcamp 2019 Intro to SPFx Version
M365 global developer bootcamp 2019 Intro to SPFx VersionThomas Daly
 
Plug yourself in and your app will never be the same (1 hr edition)
Plug yourself in and your app will never be the same (1 hr edition)Plug yourself in and your app will never be the same (1 hr edition)
Plug yourself in and your app will never be the same (1 hr edition)Mikkel Flindt Heisterberg
 
Going open source with small teams
Going open source with small teamsGoing open source with small teams
Going open source with small teamsJamie Thomas
 

Semelhante a Dive into SObjectizer 5.5. Introductory part (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)
 
React Native custom components
React Native custom componentsReact Native custom components
React Native custom components
 
Analysis of merge requests in GitLab using PVS-Studio for C#
Analysis of merge requests in GitLab using PVS-Studio for C#Analysis of merge requests in GitLab using PVS-Studio for C#
Analysis of merge requests in GitLab using PVS-Studio for C#
 
PVS-Studio and Continuous Integration: TeamCity. Analysis of the Open RollerC...
PVS-Studio and Continuous Integration: TeamCity. Analysis of the Open RollerC...PVS-Studio and Continuous Integration: TeamCity. Analysis of the Open RollerC...
PVS-Studio and Continuous Integration: TeamCity. Analysis of the Open RollerC...
 
Full Stack React Workshop [CSSC x GDSC]
Full Stack React Workshop [CSSC x GDSC]Full Stack React Workshop [CSSC x GDSC]
Full Stack React Workshop [CSSC x GDSC]
 
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
 
React Basic and Advance || React Basic
React Basic and Advance   || React BasicReact Basic and Advance   || React Basic
React Basic and Advance || React Basic
 
Diving into VS 2015 Day2
Diving into VS 2015 Day2Diving into VS 2015 Day2
Diving into VS 2015 Day2
 
3 Ways to Get Started with a React App in 2024.pdf
3 Ways to Get Started with a React App in 2024.pdf3 Ways to Get Started with a React App in 2024.pdf
3 Ways to Get Started with a React App in 2024.pdf
 
Create a meteor chat app in 30 minutes
Create a meteor chat app in 30 minutesCreate a meteor chat app in 30 minutes
Create a meteor chat app in 30 minutes
 
Reactive programming with tracker
Reactive programming with trackerReactive programming with tracker
Reactive programming with tracker
 
Errors that static code analysis does not find because it is not used
Errors that static code analysis does not find because it is not usedErrors that static code analysis does not find because it is not used
Errors that static code analysis does not find because it is not used
 
Basic iOS Training with SWIFT - Part 4
Basic iOS Training with SWIFT - Part 4Basic iOS Training with SWIFT - Part 4
Basic iOS Training with SWIFT - Part 4
 
Analysis of bugs in Orchard CMS
Analysis of bugs in Orchard CMSAnalysis of bugs in Orchard CMS
Analysis of bugs in Orchard CMS
 
Angular Optimization Web Performance Meetup
Angular Optimization Web Performance MeetupAngular Optimization Web Performance Meetup
Angular Optimization Web Performance Meetup
 
No sql injection in meteor.js application
No sql injection in meteor.js applicationNo sql injection in meteor.js application
No sql injection in meteor.js application
 
M365 global developer bootcamp 2019 Intro to SPFx Version
M365 global developer bootcamp 2019 Intro to SPFx VersionM365 global developer bootcamp 2019 Intro to SPFx Version
M365 global developer bootcamp 2019 Intro to SPFx Version
 
Plug yourself in and your app will never be the same (1 hr edition)
Plug yourself in and your app will never be the same (1 hr edition)Plug yourself in and your app will never be the same (1 hr edition)
Plug yourself in and your app will never be the same (1 hr edition)
 
Going open source with small teams
Going open source with small teamsGoing open source with small teams
Going open source with small teams
 

Mais de Yauheni 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
 
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
 
Dive into SObjectizer 5.5. Tenth part: Mutable Messages
Dive into SObjectizer 5.5. Tenth part: Mutable MessagesDive into SObjectizer 5.5. Tenth part: Mutable Messages
Dive into SObjectizer 5.5. Tenth part: Mutable MessagesYauheni Akhotnikau
 
Шишки, набитые за 15 лет использования акторов в C++
Шишки, набитые за 15 лет использования акторов в C++Шишки, набитые за 15 лет использования акторов в C++
Шишки, набитые за 15 лет использования акторов в C++Yauheni Akhotnikau
 
Для чего мы делали свой акторный фреймворк и что из этого вышло?
Для чего мы делали свой акторный фреймворк и что из этого вышло?Для чего мы делали свой акторный фреймворк и что из этого вышло?
Для чего мы делали свой акторный фреймворк и что из этого вышло?Yauheni Akhotnikau
 
Модель акторов и C++ что, зачем и как?
Модель акторов и C++ что, зачем и как?Модель акторов и C++ что, зачем и как?
Модель акторов и C++ что, зачем и как?Yauheni Akhotnikau
 
Погружение в SObjectizer 5.5. Вводная часть
Погружение в SObjectizer 5.5. Вводная частьПогружение в SObjectizer 5.5. Вводная часть
Погружение в SObjectizer 5.5. Вводная частьYauheni Akhotnikau
 

Mais de Yauheni Akhotnikau (14)

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
 
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
 
Dive into SObjectizer 5.5. Tenth part: Mutable Messages
Dive into SObjectizer 5.5. Tenth part: Mutable MessagesDive into SObjectizer 5.5. Tenth part: Mutable Messages
Dive into SObjectizer 5.5. Tenth part: Mutable Messages
 
Шишки, набитые за 15 лет использования акторов в C++
Шишки, набитые за 15 лет использования акторов в C++Шишки, набитые за 15 лет использования акторов в C++
Шишки, набитые за 15 лет использования акторов в C++
 
Для чего мы делали свой акторный фреймворк и что из этого вышло?
Для чего мы делали свой акторный фреймворк и что из этого вышло?Для чего мы делали свой акторный фреймворк и что из этого вышло?
Для чего мы делали свой акторный фреймворк и что из этого вышло?
 
Модель акторов и C++ что, зачем и как?
Модель акторов и C++ что, зачем и как?Модель акторов и C++ что, зачем и как?
Модель акторов и C++ что, зачем и как?
 
Погружение в SObjectizer 5.5. Вводная часть
Погружение в SObjectizer 5.5. Вводная частьПогружение в SObjectizer 5.5. Вводная часть
Погружение в SObjectizer 5.5. Вводная часть
 
Обзор SObjectizer 5.5
Обзор SObjectizer 5.5Обзор SObjectizer 5.5
Обзор SObjectizer 5.5
 

Último

How to submit a standout Adobe Champion Application
How to submit a standout Adobe Champion ApplicationHow to submit a standout Adobe Champion Application
How to submit a standout Adobe Champion ApplicationBradBedford3
 
Catch the Wave: SAP Event-Driven and Data Streaming for the Intelligence Ente...
Catch the Wave: SAP Event-Driven and Data Streaming for the Intelligence Ente...Catch the Wave: SAP Event-Driven and Data Streaming for the Intelligence Ente...
Catch the Wave: SAP Event-Driven and Data Streaming for the Intelligence Ente...confluent
 
cpct NetworkING BASICS AND NETWORK TOOL.ppt
cpct NetworkING BASICS AND NETWORK TOOL.pptcpct NetworkING BASICS AND NETWORK TOOL.ppt
cpct NetworkING BASICS AND NETWORK TOOL.pptrcbcrtm
 
VK Business Profile - provides IT solutions and Web Development
VK Business Profile - provides IT solutions and Web DevelopmentVK Business Profile - provides IT solutions and Web Development
VK Business Profile - provides IT solutions and Web Developmentvyaparkranti
 
A healthy diet for your Java application Devoxx France.pdf
A healthy diet for your Java application Devoxx France.pdfA healthy diet for your Java application Devoxx France.pdf
A healthy diet for your Java application Devoxx France.pdfMarharyta Nedzelska
 
MYjobs Presentation Django-based project
MYjobs Presentation Django-based projectMYjobs Presentation Django-based project
MYjobs Presentation Django-based projectAnoyGreter
 
Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...
Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...
Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...OnePlan Solutions
 
Sending Calendar Invites on SES and Calendarsnack.pdf
Sending Calendar Invites on SES and Calendarsnack.pdfSending Calendar Invites on SES and Calendarsnack.pdf
Sending Calendar Invites on SES and Calendarsnack.pdf31events.com
 
PREDICTING RIVER WATER QUALITY ppt presentation
PREDICTING  RIVER  WATER QUALITY  ppt presentationPREDICTING  RIVER  WATER QUALITY  ppt presentation
PREDICTING RIVER WATER QUALITY ppt presentationvaddepallysandeep122
 
Precise and Complete Requirements? An Elusive Goal
Precise and Complete Requirements? An Elusive GoalPrecise and Complete Requirements? An Elusive Goal
Precise and Complete Requirements? An Elusive GoalLionel Briand
 
Machine Learning Software Engineering Patterns and Their Engineering
Machine Learning Software Engineering Patterns and Their EngineeringMachine Learning Software Engineering Patterns and Their Engineering
Machine Learning Software Engineering Patterns and Their EngineeringHironori Washizaki
 
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte Germany
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte GermanySuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte Germany
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte GermanyChristoph Pohl
 
Balasore Best It Company|| Top 10 IT Company || Balasore Software company Odisha
Balasore Best It Company|| Top 10 IT Company || Balasore Software company OdishaBalasore Best It Company|| Top 10 IT Company || Balasore Software company Odisha
Balasore Best It Company|| Top 10 IT Company || Balasore Software company Odishasmiwainfosol
 
英国UN学位证,北安普顿大学毕业证书1:1制作
英国UN学位证,北安普顿大学毕业证书1:1制作英国UN学位证,北安普顿大学毕业证书1:1制作
英国UN学位证,北安普顿大学毕业证书1:1制作qr0udbr0
 
Unveiling Design Patterns: A Visual Guide with UML Diagrams
Unveiling Design Patterns: A Visual Guide with UML DiagramsUnveiling Design Patterns: A Visual Guide with UML Diagrams
Unveiling Design Patterns: A Visual Guide with UML DiagramsAhmed Mohamed
 
What is Fashion PLM and Why Do You Need It
What is Fashion PLM and Why Do You Need ItWhat is Fashion PLM and Why Do You Need It
What is Fashion PLM and Why Do You Need ItWave PLM
 
Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...
Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...
Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...OnePlan Solutions
 
Software Project Health Check: Best Practices and Techniques for Your Product...
Software Project Health Check: Best Practices and Techniques for Your Product...Software Project Health Check: Best Practices and Techniques for Your Product...
Software Project Health Check: Best Practices and Techniques for Your Product...Velvetech LLC
 

Último (20)

How to submit a standout Adobe Champion Application
How to submit a standout Adobe Champion ApplicationHow to submit a standout Adobe Champion Application
How to submit a standout Adobe Champion Application
 
Catch the Wave: SAP Event-Driven and Data Streaming for the Intelligence Ente...
Catch the Wave: SAP Event-Driven and Data Streaming for the Intelligence Ente...Catch the Wave: SAP Event-Driven and Data Streaming for the Intelligence Ente...
Catch the Wave: SAP Event-Driven and Data Streaming for the Intelligence Ente...
 
cpct NetworkING BASICS AND NETWORK TOOL.ppt
cpct NetworkING BASICS AND NETWORK TOOL.pptcpct NetworkING BASICS AND NETWORK TOOL.ppt
cpct NetworkING BASICS AND NETWORK TOOL.ppt
 
VK Business Profile - provides IT solutions and Web Development
VK Business Profile - provides IT solutions and Web DevelopmentVK Business Profile - provides IT solutions and Web Development
VK Business Profile - provides IT solutions and Web Development
 
A healthy diet for your Java application Devoxx France.pdf
A healthy diet for your Java application Devoxx France.pdfA healthy diet for your Java application Devoxx France.pdf
A healthy diet for your Java application Devoxx France.pdf
 
MYjobs Presentation Django-based project
MYjobs Presentation Django-based projectMYjobs Presentation Django-based project
MYjobs Presentation Django-based project
 
Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...
Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...
Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...
 
Sending Calendar Invites on SES and Calendarsnack.pdf
Sending Calendar Invites on SES and Calendarsnack.pdfSending Calendar Invites on SES and Calendarsnack.pdf
Sending Calendar Invites on SES and Calendarsnack.pdf
 
Advantages of Odoo ERP 17 for Your Business
Advantages of Odoo ERP 17 for Your BusinessAdvantages of Odoo ERP 17 for Your Business
Advantages of Odoo ERP 17 for Your Business
 
PREDICTING RIVER WATER QUALITY ppt presentation
PREDICTING  RIVER  WATER QUALITY  ppt presentationPREDICTING  RIVER  WATER QUALITY  ppt presentation
PREDICTING RIVER WATER QUALITY ppt presentation
 
Precise and Complete Requirements? An Elusive Goal
Precise and Complete Requirements? An Elusive GoalPrecise and Complete Requirements? An Elusive Goal
Precise and Complete Requirements? An Elusive Goal
 
Machine Learning Software Engineering Patterns and Their Engineering
Machine Learning Software Engineering Patterns and Their EngineeringMachine Learning Software Engineering Patterns and Their Engineering
Machine Learning Software Engineering Patterns and Their Engineering
 
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte Germany
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte GermanySuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte Germany
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte Germany
 
Balasore Best It Company|| Top 10 IT Company || Balasore Software company Odisha
Balasore Best It Company|| Top 10 IT Company || Balasore Software company OdishaBalasore Best It Company|| Top 10 IT Company || Balasore Software company Odisha
Balasore Best It Company|| Top 10 IT Company || Balasore Software company Odisha
 
英国UN学位证,北安普顿大学毕业证书1:1制作
英国UN学位证,北安普顿大学毕业证书1:1制作英国UN学位证,北安普顿大学毕业证书1:1制作
英国UN学位证,北安普顿大学毕业证书1:1制作
 
Unveiling Design Patterns: A Visual Guide with UML Diagrams
Unveiling Design Patterns: A Visual Guide with UML DiagramsUnveiling Design Patterns: A Visual Guide with UML Diagrams
Unveiling Design Patterns: A Visual Guide with UML Diagrams
 
What is Fashion PLM and Why Do You Need It
What is Fashion PLM and Why Do You Need ItWhat is Fashion PLM and Why Do You Need It
What is Fashion PLM and Why Do You Need It
 
Hot Sexy call girls in Patel Nagar🔝 9953056974 🔝 escort Service
Hot Sexy call girls in Patel Nagar🔝 9953056974 🔝 escort ServiceHot Sexy call girls in Patel Nagar🔝 9953056974 🔝 escort Service
Hot Sexy call girls in Patel Nagar🔝 9953056974 🔝 escort Service
 
Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...
Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...
Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...
 
Software Project Health Check: Best Practices and Techniques for Your Product...
Software Project Health Check: Best Practices and Techniques for Your Product...Software Project Health Check: Best Practices and Techniques for Your Product...
Software Project Health Check: Best Practices and Techniques for Your Product...
 

Dive into SObjectizer 5.5. Introductory part

  • 1. Dive into SObjectizer-5.5 SObjectizer Team, Jan 2016 Introductory part (at v.5.5.15)
  • 2. SObjectizer is a small framework that simplifies the development of concurrent and event-driven applications in C++. SObjectizer Team, Jan 2016
  • 3. SObjectizer was designed under the influence of several approaches. The Actor Model* is one of them. But the history of SObjectizer started long before this model became widely known. * http://en.wikipedia.org/wiki/Actor_model SObjectizer Team, Jan 2016
  • 4. SObjectizer’s main ideas and principles were formulated in the middle of 1990s, during the development of SCADA Objectizer project in Development Bureau of System Programming in Homyel, Belarus (1996-2000). SCADA Objectizer’s ideas were reused in the new project SObjectizer-4 in 2002. SObjectizer Team, Jan 2016
  • 5. Evolution of SObjectizer-4 was stopped in 2010 and the development of SObjectizer-5 started. SObjectizer Team, Jan 2016
  • 6. SObjectizer was an in-house project of JSC Intervale* for the long time. It was used in the development of the following software systems: ● SMS/USSD traffic service ● financial transaction handling ● software parameters monitoring. * www.intervale.ru SObjectizer Team, Jan 2016
  • 7. SObjectizer was published as an OpenSource project on SourceForge under 3-clauses BSD- licence in 2006. Since 2013 SObjectizer’s development completely moved to SourceForge. SObjectizer now is an independent project which is totally separated from JSC Intervale. SObjectizer Team, Jan 2016
  • 8. SObjectizer allows to build a concurrent application as a set of agent-objects... ...which interact with each other only by means of asynchronous messages. SObjectizer Team, Jan 2016
  • 9. Every agent receives its own working context. This context is used for message processing. An agent is bound to its context. It allows not to worry about defense of integrity of the agent’s data in the multithreaded environment. This defense is automatically performed by SObjectizer itself! SObjectizer Team, Jan 2016
  • 11. All SObjectizer’s work is performed inside SObjectizer Environment. SObjectizer Environment is a container for SObjectizer Run-Time, agent’s cooperations, message boxes, dispatchers and timer thread. It is possible to create several Environments in one application. Each Environment will work independently from others. SObjectizer Team, Jan 2016
  • 12. SObjectizer Environment is created by so_5::launch() function. A new instance of Environment is created and started inside so_5::launch(). The control from so_5::launch() is returned only when Environment finished its execution. What happened inside Environment is completely dependent on user supplied starting function. SObjectizer Team, Jan 2016
  • 13. It looks like that: #include <iostream> #include <so_5/all.hpp> void init( so_5::environment_t & env ) { ... } int main() { try { so_5::launch( &init ); } catch( const std::exception & x ) { std::cerr << "Exception: " << x.what() << std::endl; } } SObjectizer Team, Jan 2016
  • 14. #include <iostream> #include <so_5/all.hpp> void init( so_5::environment_t & env ) { ... } int main() { try { so_5::launch( &init ); } catch( const std::exception & x ) { std::cerr << "Exception: " << x.what() << std::endl; } } Main header file with all necessary definitions. It looks like that: SObjectizer Team, Jan 2016
  • 15. #include <iostream> #include <so_5/all.hpp> void init( so_5::environment_t & env ) { ... } int main() { try { so_5::launch( &init ); } catch( const std::exception & x ) { std::cerr << "Exception: " << x.what() << std::endl; } } User supplied starting function. It creates all application specific stuff. It looks like that: SObjectizer Team, Jan 2016
  • 16. #include <iostream> #include <so_5/all.hpp> void init( so_5::environment_t & env ) { ... } int main() { try { so_5::launch( &init ); } catch( const std::exception & x ) { std::cerr << "Exception: " << x.what() << std::endl; } } SObjectizer Environment object. Starting function will work inside it. It looks like that: SObjectizer Team, Jan 2016
  • 17. #include <iostream> #include <so_5/all.hpp> void init( so_5::environment_t & env ) { ... } int main() { try { so_5::launch( &init ); } catch( const std::exception & x ) { std::cerr << "Exception: " << x.what() << std::endl; } } Creation of Environment, starting it and invoking init() inside that Environment. Control will be returned when all application-specific agents finish their work. It looks like that: SObjectizer Team, Jan 2016
  • 18. #include <iostream> #include <so_5/all.hpp> void init( so_5::environment_t & env ) { ... } int main() { try { so_5::launch( &init ); } catch( const std::exception & x ) { std::cerr << "Exception: " << x.what() << std::endl; } } Error handling. Error reporting is done via exceptions. It looks like that: SObjectizer Team, Jan 2016
  • 19. Usually one or more agent’s cooperations are created inside the starting function. Cooperation is a group of agents which must work together and can’t exist one without another. For example: pinger and ponger agents which send ping/pong messages back and forth. There is no any sense in pinger agent without ponger agent. They must appear and disappear at the same time. SObjectizer Team, Jan 2016
  • 20. Creation of a cooperation with two agents: void init( so_5::environment_t & env ) { auto coop = env.create_coop( so_5::autoname ); coop->make_agent< pinger >(); coop->make_agent< ponger >(); env.register_coop( std::move( coop ) ); } SObjectizer Team, Jan 2016
  • 21. void init( so_5::environment_t & env ) { auto coop = env.create_coop( so_5::autoname ); coop->make_agent< pinger >(); coop->make_agent< ponger >(); env.register_coop( std::move( coop ) ); } Creation consists of three steps. At the beginning the Environment creates a cooperation... Creation of a cooperation with two agents: SObjectizer Team, Jan 2016
  • 22. void init( so_5::environment_t & env ) { auto coop = env.create_coop( so_5::autoname ); coop->make_agent< pinger >(); coop->make_agent< ponger >(); env.register_coop( std::move( coop ) ); } Then the cooperation is filled up with agents... make_agent() method is like std::make_unique from C++14. It creates dynamically allocated agent of specified type. Creation of a cooperation with two agents: SObjectizer Team, Jan 2016
  • 23. void init( so_5::environment_t & env ) { auto coop = env.create_coop( so_5::autoname ); coop->make_agent< pinger >(); coop->make_agent< ponger >(); env.register_coop( std::move( coop ) ); } Then the cooperation is being registered. Creation of a cooperation with two agents: SObjectizer Team, Jan 2016
  • 24. void init( so_5::environment_t & env ) { auto coop = env.create_coop( so_5::autoname ); coop->make_agent< pinger >(); coop->make_agent< ponger >(); env.register_coop( std::move( coop ) ); } Every cooperation must have unique name. The uniqueness is checked inside register_coop(). But SObjectizer can be asked to generate a name for the new cooperation automatically. Creation of a cooperation with two agents: SObjectizer Team, Jan 2016
  • 25. void init( so_5::environment_t & env ) { auto coop = env.create_coop( so_5::autoname ); coop->make_agent< pinger >(); coop->make_agent< ponger >(); env.register_coop( std::move( coop ) ); } Starting function finishes after cooperation registration. But the Environment will work until that cooperation will be deregistered. Or the Environment stop function will be called explicitly. Creation of a cooperation with two agents: SObjectizer Team, Jan 2016
  • 26. What is an agent? Let’s start with the simplest agent in this example. A ponger agent. SObjectizer Team, Jan 2016
  • 27. It does very simple tasks: ● receives ping messages ● replies with pong messages. So first of all let’s define those messages... SObjectizer Team, Jan 2016
  • 28. Definition of the messages: struct ping : public so_5::message_t { unsigned int m_req; ping( unsigned int req ) : m_req{ req } {} }; struct pong : public so_5::message_t { unsigned int m_resp; pong( unsigned int resp ) : m_resp{ resp } {} }; SObjectizer Team, Jan 2016
  • 29. struct ping : public so_5::message_t { unsigned int m_req; ping( unsigned int req ) : m_req{ req } {} }; struct pong : public so_5::message_t { unsigned int m_resp; pong( unsigned int resp ) : m_resp{ resp } {} }; Every message must be represented by a separate C++ class (or a structure). Message dispatching and selection of a handler are based on the message type information. Definition of the messages: SObjectizer Team, Jan 2016
  • 30. struct ping : public so_5::message_t { unsigned int m_req; ping( unsigned int req ) : m_req{ req } {} }; struct pong : public so_5::message_t { unsigned int m_resp; pong( unsigned int resp ) : m_resp{ resp } {} }; Messages types with some data inside usually derived from common base class so_5::message_t. In v. 5.5.15 it is not necessary but inheritance is shown here just for demonstration purposes. There are also messages without actual data. They are called signals. They will be described further. Definition of the messages: SObjectizer Team, Jan 2016
  • 31. struct ping : public so_5::message_t { unsigned int m_req; ping( unsigned int req ) : m_req{ req } {} }; struct pong : public so_5::message_t { unsigned int m_resp; pong( unsigned int resp ) : m_resp{ resp } {} }; SObjectizer has no significant limits for message’s content. In this particular case the m_req and m_resp fields are necessary for the sample logic. They have no relation to SObjectizer features. Definition of the messages: SObjectizer Team, Jan 2016
  • 32. ponger agent: class ponger : public so_5::agent_t { public : ponger( context_t ctx ) : so_5::agent_t( ctx ) , m_table( env.create_mbox( "table" ) ) {} virtual void so_define_agent() override { so_subscribe( m_table ).event( &ponger::evt_ping ); } private : const so_5::mbox_t m_table; void evt_ping( const ping & evt ) { so_5::send< pong >( m_table, evt.m_req ); } }; SObjectizer Team, Jan 2016
  • 33. class ponger : public so_5::agent_t { public : ponger( context_t ctx ) : so_5::agent_t( ctx ) , m_table( env.create_mbox( "table" ) ) {} virtual void so_define_agent() override { so_subscribe( m_table ).event( &ponger::evt_ping ); } private : const so_5::mbox_t m_table; void evt_ping( const ping & evt ) { so_5::send< pong >( m_table, evt.m_req ); } }; Every ordinary agent must be represented by a C++ class. There also can be non ordinary agents named ad-hoc agents. They will be described further. ponger agent: SObjectizer Team, Jan 2016
  • 34. class ponger : public so_5::agent_t { public : ponger( context_t ctx ) : so_5::agent_t( ctx ) , m_table( env.create_mbox( "table" ) ) {} virtual void so_define_agent() override { so_subscribe( m_table ).event( &ponger::evt_ping ); } private : const so_5::mbox_t m_table; void evt_ping( const ping & evt ) { so_5::send< pong >( m_table, evt.m_req ); } }; Class of ordinary agent must be derived from common base type so_5::agent_t. ponger agent: SObjectizer Team, Jan 2016
  • 35. ponger agent: class ponger : public so_5::agent_t { public : ponger( context_t ctx ) : so_5::agent_t( ctx ) , m_table( env.create_mbox( "table" ) ) {} virtual void so_define_agent() override { so_subscribe( m_table ).event( &ponger::evt_ping ); } private : const so_5::mbox_t m_table; void evt_ping( const ping & evt ) { so_5::send< pong >( m_table, evt.m_req ); } }; Every agent must be bound to an Environment where an agent will work. Because of that a reference to Environment object must be passed to the agent’s constructor and redirected to the constructor of the base type so_5::agent_t. A reference to Environment is inside of context_t object. SObjectizer Team, Jan 2016
  • 36. ponger agent: class ponger : public so_5::agent_t { public : ponger( context_t ctx ) : so_5::agent_t( ctx ) , m_table( env.create_mbox( "table" ) ) {} virtual void so_define_agent() override { so_subscribe( m_table ).event( &ponger::evt_ping ); } private : const so_5::mbox_t m_table; void evt_ping( const ping & evt ) { so_5::send< pong >( m_table, evt.m_req ); } }; SObjectizer calls so_define_agent() method before an agent will be registered. Agent must perform all necessary tuning actions in this method. Create message subscriptions in particular. SObjectizer Team, Jan 2016
  • 37. class ponger : public so_5::agent_t { public : ponger( context_t ctx ) : so_5::agent_t( ctx ) , m_table( env.create_mbox( "table" ) ) {} virtual void so_define_agent() override { so_subscribe( m_table ).event( &ponger::evt_ping ); } private : const so_5::mbox_t m_table; void evt_ping( const ping & evt ) { so_5::send< pong >( m_table, evt.m_req ); } }; Ponger agent subscribes only to one message of ping type. This message is going from a message box with name “table”. Message box must be specified explicitly. But the message type is deduced by SObjectizer automatically from the message handler signature. ponger agent: SObjectizer Team, Jan 2016
  • 38. class ponger : public so_5::agent_t { public : ponger( context_t ctx ) : so_5::agent_t( ctx ) , m_table( env.create_mbox( "table" ) ) {} virtual void so_define_agent() override { so_subscribe( m_table ).event( &ponger::evt_ping ); } private : const so_5::mbox_t m_table; void evt_ping( const ping & evt ) { so_5::send< pong >( m_table, evt.m_req ); } }; A message handler method is named event handler method. Or just event. ponger agent: SObjectizer Team, Jan 2016
  • 39. class ponger : public so_5::agent_t { public : ponger( context_t ctx ) : so_5::agent_t( ctx ) , m_table( env.create_mbox( "table" ) ) {} virtual void so_define_agent() override { so_subscribe( m_table ).event( &ponger::evt_ping ); } private : const so_5::mbox_t m_table; void evt_ping( const ping & evt ) { so_5::send< pong >( m_table, evt.m_req ); } }; A message instance which caused an event is passed to event handler by const reference. Event handler must not modify that message instance because it can be handled by the different agents at the same time. ponger agent: SObjectizer Team, Jan 2016
  • 40. Agent replies by sending a pong message instance to the message box with name “table”. ponger agent: class ponger : public so_5::agent_t { public : ponger( context_t ctx ) : so_5::agent_t( ctx ) , m_table( env.create_mbox( "table" ) ) {} virtual void so_define_agent() override { so_subscribe( m_table ).event( &ponger::evt_ping ); } private : const so_5::mbox_t m_table; void evt_ping( const ping & evt ) { so_5::send< pong >( m_table, evt.m_req ); } }; SObjectizer Team, Jan 2016
  • 41. class ponger : public so_5::agent_t { public : ponger( context_t ctx ) : so_5::agent_t( ctx ) , m_table( env.create_mbox( "table" ) ) {} virtual void so_define_agent() override { so_subscribe( m_table ).event( &ponger::evt_ping ); } private : const so_5::mbox_t m_table; void evt_ping( const ping & evt ) { so_5::send< pong >( m_table, evt.m_req ); } }; so_5::send() template function constructs an object of pong type and sends it to the message box specified. ponger agent: SObjectizer Team, Jan 2016
  • 42. class ponger : public so_5::agent_t { public : ponger( context_t ctx ) : so_5::agent_t( ctx ) , m_table( env.create_mbox( "table" ) ) {} virtual void so_define_agent() override { so_subscribe( m_table ).event( &ponger::evt_ping ); } private : const so_5::mbox_t m_table; void evt_ping( const ping & evt ) { so_5::send< pong >( m_table, evt.m_req ); } }; All arguments after message box are passed to the message object’ s constructor. In this case it is resp argument for the pong’s constructor. ponger agent: SObjectizer Team, Jan 2016
  • 43. class ponger : public so_5::agent_t { public : ponger( context_t ctx ) : so_5::agent_t( ctx ) , m_table( env.create_mbox( "table" ) ) {} virtual void so_define_agent() override { so_subscribe( m_table ).event( &ponger::evt_ping ); } private : const so_5::mbox_t m_table; void evt_ping( const ping & evt ) { so_5::send< pong >( m_table, evt.m_req ); } }; Ponger agent gets a reference to the message box for message exchange by itself. In this case it is a message box with name “table”. This box is created by invocation of create_mbox(). A reference to message box is stored inside the agent. ponger agent: SObjectizer Team, Jan 2016
  • 44. pinger agent (beginning): class pinger : public so_5::agent_t { public : pinger( context_t ctx ) : so_5::agent_t( ctx ) , m_table( env.create_mbox( "table" ) ) {} virtual void so_define_agent() override { so_subscribe( m_table ).event( &pinger::evt_pong ); } virtual void so_evt_start() override { so_5::send< ping >( m_table, 500 ); } SObjectizer Team, Jan 2016
  • 45. class pinger : public so_5::agent_t { public : pinger( context_t ctx ) : so_5::agent_t( ctx ) , m_table( env.create_mbox( "table" ) ) {} virtual void so_define_agent() override { so_subscribe( m_table ).event( &pinger::evt_pong ); } virtual void so_evt_start() override { so_5::send< ping >( m_table, 500 ); } Pinger agent is very similar to the ponger agent: receives a context_t object in its constructor and creates a reference to message box with name “table”. Pinger also subscribes to a single message in so_define_agent(). pinger agent (beginning): SObjectizer Team, Jan 2016
  • 46. class pinger : public so_5::agent_t { public : pinger( context_t ctx ) : so_5::agent_t( ctx ) , m_table( env.create_mbox( "table" ) ) {} virtual void so_define_agent() override { so_subscribe( m_table ).event( &pinger::evt_pong ); } virtual void so_evt_start() override { so_5::send< ping >( m_table, 500 ); } But there is one significant distinction: so_evt_start() method. This method is called just after successful registration of the agent’s cooperation. An agent can perform any starting actions in that method. In this particular case: sends the very first ping message. pinger agent (beginning): SObjectizer Team, Jan 2016
  • 47. pinger agent (ending): private : const so_5::mbox_t m_table; void evt_pong( const pong & evt ) { if( evt.m_resp ) so_5::send< ping >( m_table, evt.m_resp - 1 ); else so_deregister_agent_coop_normally(); } }; SObjectizer Team, Jan 2016
  • 48. pinger agent (ending): private : const so_5::mbox_t m_table; void evt_pong( const pong & evt ) { if( evt.m_resp ) so_5::send< ping >( m_table, evt.m_resp - 1 ); else so_deregister_agent_coop_normally(); } }; In the evt_pong() the agent can continue the message exchange by sending the next ping message. Or, in the case when all messages have been sent, cooperation deregistration can be initiated. SObjectizer Team, Jan 2016
  • 49. pinger agent (ending): private : const so_5::mbox_t m_table; void evt_pong( const pong & evt ) { if( evt.m_resp ) so_5::send< ping >( m_table, evt.m_resp - 1 ); else so_deregister_agent_coop_normally(); } }; The reasons for deregistering a cooperation might be different. In this case the deregistration is a normal part of the application logic. There will be no live cooperations after deregistration of pinger/ponger cooperation. So Environment will finish its work and so_5::launch will return control to the caller. SObjectizer Team, Jan 2016
  • 50. Few words about message boxes (mboxes)... Despite other similar tools like Erlang, Akka or CAF, in SObjectizer a message is sent not to an agent, but to a message box (mbox). There could be one agent behind the mbox. Or many agents. Or none. SObjectizer Team, Jan 2016
  • 51. There are two types of mboxes in SObjectizer: SObjectizer Team, Jan 2016
  • 52. Multi-Producers/Multi-Consumers mboxes. They are like “bulletin boards”. A message sent to such mbox becomes available for all subscribers of the mbox. MPMC-mbox is shown in the code above. SObjectizer Team, Jan 2016
  • 53. Multi-Producers/Single-Consumer mboxes. Mboxes of that type have only one subscriber. It is an agent who owns such mbox. SObjectizer Team, Jan 2016
  • 54. Lets add another agent to the example to show specifics of MPMC-mboxes... This agent will listen the message exchange between pinger and ponger agents, and will count the messages sent. SObjectizer Team, Jan 2016
  • 55. listener agent: class listener : public so_5::agent_t { public : listener( context_t ctx ) : so_5::agent_t( ctx ) , m_table( env.create_mbox( "table" ) ) {} virtual void so_define_agent() override { so_subscribe( m_table ) .event( [this]( const ping & ) { ++m_pings; } ) .event( [this]( const pong & ) { ++m_pongs; } ); } virtual void so_evt_finish() override { std::cout << "result: " << m_pings << "/" << m_pongs << std::endl; } private : const so_5::mbox_t m_table; unsigned int m_pings = 0; unsigned int m_pongs = 0; }; SObjectizer Team, Jan 2016
  • 56. listener agent: class listener : public so_5::agent_t { public : listener( context_t ctx ) : so_5::agent_t( ctx ) , m_table( env.create_mbox( "table" ) ) {} virtual void so_define_agent() override { so_subscribe( m_table ) .event( [this]( const ping & ) { ++m_pings; } ) .event( [this]( const pong & ) { ++m_pongs; } ); } virtual void so_evt_finish() override { std::cout << "result: " << m_pings << "/" << m_pongs << std::endl; } private : const so_5::mbox_t m_table; unsigned int m_pings = 0; unsigned int m_pongs = 0; }; It is necessary to receive two messages. Because of that the agent subscribes two events. Lambda-functions are used instead of event handler methods. Types of messages are automatically deduced from lambdas signatures. SObjectizer Team, Jan 2016
  • 57. listener agent: class listener : public so_5::agent_t { public : listener( context_t ctx ) : so_5::agent_t( ctx ) , m_table( env.create_mbox( "table" ) ) {} virtual void so_define_agent() override { so_subscribe( m_table ) .event( [this]( const ping & ) { ++m_pings; } ) .event( [this]( const pong & ) { ++m_pongs; } ); } virtual void so_evt_finish() override { std::cout << "result: " << m_pings << "/" << m_pongs << std::endl; } private : const so_5::mbox_t m_table; unsigned int m_pings = 0; unsigned int m_pongs = 0; }; so_evt_finish() method is the opposite to so_evt_start(). It is called for agent just before the very end of agent’s work. In this case that method is used for result printing. SObjectizer Team, Jan 2016
  • 58. If we add a listener to the cooperation: void init( so_5::environment_t & env ) { auto coop = env.create_coop( so_5::autoname ); coop->make_agent< pinger >(); coop->make_agent< ponger >(); coop->make_agent< listener >(); env.register_coop( std::move( coop ) ); } SObjectizer Team, Jan 2016
  • 59. Then we will see at the end: result: 501/501 It means that message sending to MPMC-mbox is a broadcast message sending. SObjectizer Team, Jan 2016
  • 60. MPMC-mboxes must be created manually. MPSC-mboxes, in contradiction, are created automatically for every agent. It means that every agent has its own MPSC-mbox. In SObjectizer's terms such mbox is often named direct_mbox. SObjectizer Team, Jan 2016
  • 61. When a message is sent to MPSC-mbox it will go to mbox owner for processing. Or just discarded if mbox owner is not subscribed to that message. It means that if two agents interact via direct_mboxes nobody can listen them. SObjectizer Team, Jan 2016
  • 62. But direct_mboxes are used not for creation of a “private channels” for message exchanges. Direct_mboxes are more efficient than MPMC- mboxes. Dispatching for direct_mboxes is simpler and requires fewer internal locks. Therefore usage of direct_mboxes is more preferable if application logic doesn’t require broadcast message sending. SObjectizer Team, Jan 2016
  • 63. There is no need in broadcast message sending in the example above. Lets rewrite it with direct_mboxes. And throw out a listener agent. Lets pinger and ponger agent count the messages by themselves. And replace messages with signals. SObjectizer Team, Jan 2016
  • 64. A signal is a special case of a message when only the fact of the message existence is important. But the message itself has no any data inside. It is like sending of atoms in Erlang, when only an atom is sent without any additional data. SObjectizer Team, Jan 2016
  • 65. In the application code written with SObjectizer signals are so widely used that SObjectizer’s API was extended to simplify usage of signals. At the API level the work with signal is very similar to the work with messages. Sometimes. Sometimes not. SObjectizer Team, Jan 2016
  • 66. Replace ping and pong messages with signals... SObjectizer Team, Jan 2016
  • 67. Replace ping and pong messages with signals... SObjectizer Team, Jan 2016 struct ping : public so_5::message_t { unsigned int m_req; ping( unsigned int req ) : m_req{ req } {} }; struct pong : public so_5::message_t { unsigned int m_resp; pong( unsigned int resp ) : m_resp{ resp } {} }; struct ping : public so_5::signal_t {}; struct pong : public so_5::signal_t {};
  • 68. Replace ping and pong messages with signals... SObjectizer Team, Jan 2016 struct ping : public so_5::message_t { unsigned int m_req; ping( unsigned int req ) : m_req{ req } {} }; struct pong : public so_5::message_t { unsigned int m_resp; pong( unsigned int resp ) : m_resp{ resp } {} }; struct ping : public so_5::signal_t {}; struct pong : public so_5::signal_t {}; Signal types must be derived from so_5::signal_t and must not contain any data inside.
  • 69. Changing of pinger agent (beginning): class pinger : public so_5::agent_t { public : pinger( context_t ctx ) : so_5::agent_t( ctx ) {} void set_ponger_mbox( const so_5::mbox_t & mbox ) { m_ponger = mbox; } virtual void so_define_agent() override { so_subscribe_self().event< pong >( [this]{ ++m_pongs; so_5::send< ping >( m_ponger ); } ); } SObjectizer Team, Jan 2016
  • 70. Changing of pinger agent (beginning): class pinger : public so_5::agent_t { public : pinger( context_t ctx ) : so_5::agent_t( ctx ) {} void set_ponger_mbox( const so_5::mbox_t & mbox ) { m_ponger = mbox; } virtual void so_define_agent() override { so_subscribe_self().event< pong >( [this]{ ++m_pongs; so_5::send< ping >( m_ponger ); } ); } A direct_mbox can be accessed only after the agent creation. Because of that a separate method is needed for connecting of pinger and ponger agents. It will be called after instantiation of the agent. SObjectizer Team, Jan 2016
  • 71. Changing of pinger agent (beginning): class pinger : public so_5::agent_t { public : pinger( context_t ctx ) : so_5::agent_t( ctx ) {} void set_ponger_mbox( const so_5::mbox_t & mbox ) { m_ponger = mbox; } virtual void so_define_agent() override { so_subscribe_self().event< pong >( [this]{ ++m_pongs; so_5::send< ping >( m_ponger ); } ); } so_subscribe_self() method is used for subscription to message from agent's direct_mbox. Method event receives a lambda- function with reaction to pong signal. SObjectizer Team, Jan 2016
  • 72. Changing of pinger agent (beginning): class pinger : public so_5::agent_t { public : pinger( context_t ctx ) : so_5::agent_t( ctx ) {} void set_ponger_mbox( const so_5::mbox_t & mbox ) { m_ponger = mbox; } virtual void so_define_agent() override { so_subscribe_self().event< pong >( [this]{ ++m_pongs; so_5::send< ping >( m_ponger ); } ); } The signal type must be explicitly specified during subscription. A method or lambda-function without argument can only be used as signal handler. Unlike a message there is no a signal instance to be passed to a handler. Because of that there is no way to deduce signal type by the event handler’s signature. SObjectizer Team, Jan 2016
  • 73. Changing of pinger agent (ending): virtual void so_evt_start() override { so_5::send< ping >( m_ponger ); } virtual void so_evt_finish() override { std::cout << "pongs: " << m_pongs << std::endl; } private : so_5::mbox_t m_ponger; unsigned int m_pongs = 0; }; SObjectizer Team, Jan 2016
  • 74. Changing of pinger agent (ending): virtual void so_evt_start() override { so_5::send< ping >( m_ponger ); } virtual void so_evt_finish() override { std::cout << "pongs: " << m_pongs << std::endl; } private : so_5::mbox_t m_ponger; unsigned int m_pongs = 0; }; Signal sending is performed by the same so_5::send() function. Like a message sending. But there is no any other arguments after receiver mbox. SObjectizer Team, Jan 2016
  • 75. Similar changes to a ponger agent (beginning): class ponger : public so_5::agent_t { public : ponger( context_t ctx ) : so_5::agent_t( ctx) {} void set_pinger_mbox( const so_5::mbox_t & mbox ) { m_pinger = mbox; } virtual void so_define_agent() override { so_subscribe_self().event< ping >( [this]{ ++m_pings; so_5::send< pong >( m_pinger ); } ); } SObjectizer Team, Jan 2016
  • 76. Similar changes to a ponger agent (ending): virtual void so_evt_finish() override { std::cout << "pings: " << m_pings << std::endl; } private : so_5::mbox_t m_pinger; unsigned int m_pings = 0; }; SObjectizer Team, Jan 2016
  • 77. Creation of the cooperation becomes more verbose: void init( so_5::environment_t & env ) { auto coop = env.create_coop( so_5::autoname ); auto a_pinger = coop->make_agent< pinger >(); auto a_ponger = coop->make_agent< ponger >(); a_pinger->set_ponger_mbox( a_ponger->so_direct_mbox() ); a_ponger->set_pinger_mbox( a_pinger->so_direct_mbox() ); env.register_coop( std::move( coop ) ); } SObjectizer Team, Jan 2016
  • 78. Moreover there is an error... SObjectizer Team, Jan 2016
  • 79. No one stops them! They will ping each other infinitely. SObjectizer Team, Jan 2016
  • 80. Fix this problem by adding another agent that will stop example after one second... SObjectizer Team, Jan 2016
  • 81. Because this agent will handle only one event there is no need to define a separate class for it, redefine so_define_agent() method and so on... An ad-hoc agent will be used instead. SObjectizer Team, Jan 2016
  • 82. Ad-hoc agent for stopping the work after one second: struct stop : public so_5::signal_t {}; auto stopper = coop->define_agent(); stopper.event< stop >( stopper, [&env]{ env.stop(); } ); SObjectizer Team, Jan 2016
  • 83. Ad-hoc agent for stopping the work after one second: struct stop : public so_5::signal_t {}; auto stopper = coop->define_agent(); stopper.event< stop >( stopper, [&env]{ env.stop(); } ); Stop signal. SObjectizer Team, Jan 2016
  • 84. Ad-hoc agent for stopping the work after one second: struct stop : public so_5::signal_t {}; auto stopper = coop->define_agent(); stopper.event< stop >( stopper, [&env]{ env.stop(); } ); Ad-hoc agent creation. A handle is returned. This handle can be used for agent tuning. SObjectizer Team, Jan 2016
  • 85. Ad-hoc agent for stopping the work after one second: struct stop : public so_5::signal_t {}; auto stopper = coop->define_agent(); stopper.event< stop >( stopper, [&env]{ env.stop(); } ); The new agent is subscribed to just one signal. SObjectizer Team, Jan 2016
  • 86. Ad-hoc agent for stopping the work after one second: struct stop : public so_5::signal_t {}; auto stopper = coop->define_agent(); stopper.event< stop >( stopper, [&env]{ env.stop(); } ); Signal is expected from direct_mbox of the the agent. SObjectizer Team, Jan 2016
  • 87. Ad-hoc agent for stopping the work after one second: struct stop : public so_5::signal_t {}; auto stopper = coop->define_agent(); stopper.event< stop >( stopper, [&env]{ env.stop(); } ); The signal handler will stop SObjectizer Environment. The single cooperation will be deregistered automatically. SObjectizer Team, Jan 2016
  • 88. Ad-hoc agent is created and tuned. A delayed for one second stop signal must be sent: env.register_coop( std::move( coop ) ); so_5::send_delayed< stop >( stopper, std::chrono::seconds(1) ); SObjectizer Team, Jan 2016
  • 89. Ad-hoc agent is created and tuned. A delayed for one second stop signal must be sent: env.register_coop( std::move( coop ) ); so_5::send_delayed< stop >( stopper, std::chrono::seconds(1) ); A so_5::send_delayed function make delayed send of a signal or a message. In this case a stop signal will be sent to the direct_mbox of the new ad-hoc agent with one second delay. SObjectizer Team, Jan 2016
  • 90. Finally the starting function becomes: void init( so_5::environment_t & env ) { auto coop = env.create_coop( so_5::autoname ); auto a_pinger = coop->make_agent< pinger >(); auto a_ponger = coop->make_agent< ponger >(); a_pinger->set_ponger_mbox( a_ponger->so_direct_mbox() ); a_ponger->set_pinger_mbox( a_pinger->so_direct_mbox() ); struct stop : public so_5::signal_t {}; auto stopper = coop->define_agent(); stopper.event< stop >( stopper, [&env]{ env.stop(); } ); env.register_coop( std::move( coop ) ); so_5::send_delayed< stop >( stopper, std::chrono::seconds(1) ); } SObjectizer Team, Jan 2016
  • 91. Running the updated example... pongs: 4441168 pings: 4441169 SObjectizer Team, Jan 2016
  • 92. Just above 8M messages per seconds. Core i7 2.4GHz, 8GiB RAM, Win8.1 64-bit, Visual C++ 13.0 64-bit. SObjectizer Team, Jan 2016
  • 93. So far, so good. But which working context has been used? SObjectizer Team, Jan 2016
  • 94. All agents were working on a single thread! This example just shows the effectiveness of message passing between agents which are working on the same context. But who choose the context? And how an agent can be bound to another context? SObjectizer Team, Jan 2016
  • 95. A programmer makes choice of context when binds an agent to a dispatcher. If dispatcher is not specified then an agent will be bound to default dispatcher. Just like in the example above. SObjectizer Team, Jan 2016
  • 96. The default dispatcher runs all the agents on a single working thread. There is a something like “cooperative multitasking” for agents on the default dispatcher. If one of them will slow down the other will slow down too. But it is possible to create any number of various dispatchers and bind agents to the them. SObjectizer Team, Jan 2016
  • 97. Lets bind pinger and ponger agent to different working threads (every agent will have its own dedicated working thread)... An instance of active_obj dispatcher will be created for that. Agents will be bound to it. This dispatcher creates a dedicated thread for each agent bound to it (an agent becomes an active object). SObjectizer Team, Jan 2016
  • 98. There is nothing to change inside the agents... All the changes will be in the starting function only. SObjectizer Team, Jan 2016
  • 99. Binding of the agents to different dispatches: void init( so_5::environment_t & env ) { auto coop = env.create_coop( so_5::autoname, so_5::disp::active_obj::create_private_disp( env )->binder() ); auto a_pinger = coop->make_agent< pinger >(); auto a_ponger = coop->make_agent< ponger >(); a_pinger->set_ponger_mbox( a_ponger->so_direct_mbox() ); a_ponger->set_pinger_mbox( a_pinger->so_direct_mbox() ); struct stop : public so_5::signal_t {}; auto stopper = coop->define_agent( so_5::create_default_disp_binder() ); stopper.event< stop >( stopper, [&env]{ env.stop(); } ); env.register_coop( std::move( coop ) ); so_5::send_delayed< stop >( env, stopper, std::chrono::seconds(1) ); } SObjectizer Team, Jan 2016
  • 100. Binding of the agents to different dispatches: void init( so_5::environment_t & env ) { auto coop = env.create_coop( so_5::autoname, so_5::disp::active_obj::create_private_disp( env )->binder() ); auto a_pinger = coop->make_agent< pinger >(); auto a_ponger = coop->make_agent< ponger >(); a_pinger->set_ponger_mbox( a_ponger->so_direct_mbox() ); a_ponger->set_pinger_mbox( a_pinger->so_direct_mbox() ); struct stop : public so_5::signal_t {}; auto stopper = coop->define_agent( so_5::create_default_disp_binder() ); stopper.event< stop >( stopper, [&env]{ env.stop(); } ); env.register_coop( std::move( coop ) ); so_5::send_delayed< stop >( env, stopper, std::chrono::seconds(1) ); } Creation of the active objects dispatcher. A binder for that dispatcher will be used as main dispatcher binder for the new coop. SObjectizer Team, Jan 2016
  • 101. Binding of the agents to different dispatches: void init( so_5::environment_t & env ) { auto coop = env.create_coop( so_5::autoname, so_5::disp::active_obj::create_private_disp( env )->binder() ); auto a_pinger = coop->make_agent< pinger >(); auto a_ponger = coop->make_agent< ponger >(); a_pinger->set_ponger_mbox( a_ponger->so_direct_mbox() ); a_ponger->set_pinger_mbox( a_pinger->so_direct_mbox() ); struct stop : public so_5::signal_t {}; auto stopper = coop->define_agent( so_5::create_default_disp_binder() ); stopper.event< stop >( stopper, [&env]{ env.stop(); } ); env.register_coop( std::move( coop ) ); so_5::send_delayed< stop >( env, stopper, std::chrono::seconds(1) ); } Pinger and ponger agents are being added to the cooperation without any additional information. It means they will be bound to the main cooperation dispatcher. It is the active_obj dispatcher created above. SObjectizer Team, Jan 2016
  • 102. Binding of the agents to different dispatches: void init( so_5::environment_t & env ) { auto coop = env.create_coop( so_5::autoname, so_5::disp::active_obj::create_private_disp( env )->binder() ); auto a_pinger = coop->make_agent< pinger >(); auto a_ponger = coop->make_agent< ponger >(); a_pinger->set_ponger_mbox( a_ponger->so_direct_mbox() ); a_ponger->set_pinger_mbox( a_pinger->so_direct_mbox() ); struct stop : public so_5::signal_t {}; auto stopper = coop->define_agent( so_5::create_default_disp_binder() ); stopper.event< stop >( stopper, [&env]{ env.stop(); } ); env.register_coop( std::move( coop ) ); so_5::send_delayed< stop >( env, stopper, std::chrono::seconds(1) ); } But there is no need for a separate thread for stopper agent. Because of that this agent is being bound to the default dispatcher explicitly. Without this the stopper will be bound to the cooperation main dispatcher. SObjectizer Team, Jan 2016
  • 103. What we get now? SObjectizer Team, Jan 2016
  • 104. What we get now? pings: pongs: 1234623 1234624 SObjectizer Team, Jan 2016
  • 105. Is it ok? SObjectizer Team, Jan 2016
  • 106. Yes. It is. And there could be more strange results. But what happened? SObjectizer Team, Jan 2016
  • 107. Pinger and ponger agents are now working on different threads and compete for std::cout object. As result the output to std::cout got mixed. It could be even worse. Or could not be mixed at all. This is concurrency in action... SObjectizer Team, Jan 2016
  • 108. pings: pongs: 1234623 1234624 What else? SObjectizer Team, Jan 2016
  • 109. The performance has dropped. We have seen 8M messages per second on one thread. And just 2M on two threads. It is expected result. Passing a single message from thread to thread is an expensive operation. SObjectizer Team, Jan 2016
  • 110. But is there any changes in the agents? SObjectizer Team, Jan 2016
  • 111. Ponger agent for one thread: class ponger : public so_5::agent_t { public : ponger( context_t ctx ) : so_5::agent_t( ctx ) {} void set_pinger_mbox( const so_5::mbox_t & mbox ) { m_pinger = mbox; } virtual void so_define_agent() override { so_subscribe_self().event< ping >( [this]{ ++m_pings; so_5::send< pong >( m_pinger ); } ); } virtual void so_evt_finish() override { std::cout << "pings: " << m_pings << std::endl; } private : so_5::mbox_t m_pinger; unsigned int m_pings = 0; }; SObjectizer Team, Jan 2016
  • 112. class ponger : public so_5::agent_t { public : ponger( context_t ctx ) : so_5::agent_t( ctx ) {} void set_pinger_mbox( const so_5::mbox_t & mbox ) { m_pinger = mbox; } virtual void so_define_agent() override { so_subscribe_self().event< ping >( [this]{ ++m_pings; so_5::send< pong >( m_pinger ); } ); } virtual void so_evt_finish() override { std::cout << "pings: " << m_pings << std::endl; } private : so_5::mbox_t m_pinger; unsigned int m_pings = 0; }; Ponger agent for two threads: class ponger : public so_5::agent_t { public : ponger( context_t ctx ) : so_5::agent_t( ctx ) {} void set_pinger_mbox( const so_5::mbox_t & mbox ) { m_pinger = mbox; } virtual void so_define_agent() override { so_subscribe_self().event< ping >( [this]{ ++m_pings; so_5::send< pong >( m_pinger ); } ); } virtual void so_evt_finish() override { std::cout << "pings: " << m_pings << std::endl; } private : so_5::mbox_t m_pinger; unsigned int m_pings = 0; }; SObjectizer Team, Jan 2016 Ponger agent for one thread:
  • 113. It is a direct consequence of interaction only by asynchronous messages. Because of that agents are unaware about working context. Providing an appropriate set of different dispatchers is a task of SObjectizer. SObjectizer Team, Jan 2016
  • 114. SObjectizer has several ready-to-use dispatchers. There are one_thread, active_obj, active_group, thread_pool, adv_thread_pool and three more dispatchers which support priorities of agents... SObjectizer Team, Jan 2016
  • 115. A programmer can not only select the appropriate type of a dispatcher... ...but can create any number of those dispatchers. SObjectizer Team, Jan 2016
  • 116. For example: ● one one_thread dispatcher for AMQP-client agent; ● one thread_pool dispatcher for handling requests from AMQP-queues; ● one active_obj dispatcher for DBMS-related agents; ● yet another active_obj dispatcher for agents whose work with HSMs connected to the computer; ● and yet another thread_pool dispatcher for agents for managing all the stuff described above. SObjectizer Team, Jan 2016
  • 117. But there are yet more SObjectizer features... Such important things like: ● agent’s states ● periodic messages ● synchronous agents interaction ● child cooperation ● exception handling ● Run-Time parameters tuning and so on... SObjectizer Team, Jan 2016
  • 118. ...will be described in a more deep dive But introductory part is finished. SObjectizer Team, Jan 2016
  • 119. 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