Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

What is SObjectizer 5.5


Published on

This is a short presentation with the answer to the question "What is SObjectizer?"

Published in: Software
  • Be the first to comment

What is SObjectizer 5.5

  1. 1. What is SObjectizer-5.5? (at version 5.5.19) SObjectizer Team, May 2017
  2. 2. SObjectizer is a small tool for simplification of development of concurrent and event-driven applications in C++. SObjectizer is responsible for: ● in-process message dispatching; ● providing working thread for message processing; ● SObjectizer Run-Time’s parameters tuning. SObjectizer Team, May 2017
  3. 3. SObjectizer can be used for development of not only small utilities but also of a large, distributed and highly loaded software systems. The whole application can be build upon SObjectizer. Or SObjectizer can be used only as small part of an application developed on the top of Qt, wxWidgets, ACE, Boost, etc. SObjectizer Team, May 2017
  4. 4. 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 was designed under the influence of several approaches. And the Actor Model* is one of them. But the history of SObjectizer started long before this model became widely known. * SObjectizer Team, May 2017
  5. 5. 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. Evolution of SObjectizer-4 was stopped in 2010 and the development of SObjectizer-5 started. SObjectizer Team, May 2017
  6. 6. SObjectizer was an in-house project of JSC Intervale* for the long time. SObjectizer was used in the development of the following software systems: ● SMS/USSD traffic service; ● financial transaction handling; ● software parameters monitoring. * SObjectizer Team, May 2017
  7. 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 a totally separated from JSC Intervale. SObjectizer Team, May 2017
  8. 8. SObjectizer-5 is developed using C++11 with broad usage of C++11 standard library. Supported platforms and compilers: ● Visual C++ 12.0/14.0/15.0, GCC 4.8-7.1, clang 3.9/4.0 on Windows ● GCC 4.8-6.3, clang 3.4-4.0 on Linux, FreeBSD and MacOS; ● GCC 5.3, clang 3.7 on Android (via CrystaX NDK). Support of other platforms is possible in the case when SObjectizer’s developers will have an access to those platforms. SObjectizer Team, May 2017
  9. 9. More than 20 releases of SObjectizer-5 were published since May 2013. The last stable version ‒ 5.5.19, was published in May 2017. Version 5.5.19 is ~29 KLOC of SObjectizer core. Plus ~33 KLOC of tests. Plus ~10 KLOC of samples. Plus SObjectizer’s core documentation*. Plus articles and presentations** (some of them in Russian). * ** SObjectizer Team, May 2017
  10. 10. Using SObjectizer-5.5 a programmer must define messages/signals and implement agents for processing them. Agents are created by the programmer and are bound to dispatchers. Dispatchers are responsible for message dispatching and providing of working thread on which agents handle messages. SObjectizer Team, May 2017
  11. 11. SObjectizer has several ready-to-use dispatchers: ● one_thread. All agents work on a single working thread; ● active_obj. Every agent works on a single dedicated working thread; ● active_group. A single dedicated working thread is allocated for a group of agents; ● thread_pool. A working thread is selected from thread pool. Agents can be moved from one working thread to another. But an agent can’t work on two threads at the same time; ● adv_thread_pool. A working thread is selected from thread pool. Agents can be moved from one working thread to another. Moreover an agent can work on several threads at the same time (if the agent’s event handlers are marked as thread safe); ● prio_one_thread (strictly_ordered and quoted_round_robin). One working thread and dispatching with respect to agent’s priorities; ● prio_dedicated_threads::one_per_prio. One working thread per a priority. SObjectizer Team, May 2017
  12. 12. A programmer can create any number of dispatchers needed. This allows to bind agents to different context in such a way that the impact of one agent on another will be minimal. 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, May 2017
  13. 13. A programmer can create as many agents as he needs. Agent is a lightweight entity. There could be thousands, millions and hundreds of millions of agents. Number of agents is limited only by amount of RAM and the common sense of a programmer. SObjectizer Team, May 2017
  14. 14. There is an SObjectizer example which demonstrates almost all key features of SObjectizer-5.5: ● agent’s states, ● messages and signals, ● parent and children cooperations, ● dispatchers, ● delayed messages and so on... SObjectizer Team, May 2017
  15. 15. Parent agent creates pinger and pointer agent pair. They do message exchange for one second. After one second the parent agent deregisters pinger and ponger. On finish pinger and ponger tell the parent how many messages they received. SObjectizer Team, May 2017
  16. 16. Example Code (signals and message definition): #include <iostream> #include <string> // Main SObjectizer header file. #include <so_5/all.hpp> // Ping signal. // Signal is a special kind of message without actual data. // Sending of signals is like sending only atoms in Erlang. struct ping : public so_5::signal_t {}; // Pong signal. struct pong : public so_5::signal_t {}; // Message with result of pinger/ponger run. // Unlike signal message must have actual data. // Can be derived from so_5::message_t, but // since v.5.5.9 it is not necessary. struct run_result { std::string m_result; }; SObjectizer Team, May 2017
  17. 17. Example Code (pinger agent, beginning): // Pinger agent. class pinger : public so_5::agent_t { public : pinger( context_t ctx, so_5::mbox_t parent ) : so_5::agent_t{ ctx } // A working context. , m_parent{ std::move(parent) } // Parent's mbox for result sending. {} // Ponger mbox will be available only after creation of pinger/ponger pair. void set_ponger_mbox( const so_5::mbox_t & mbox ) { m_ponger = mbox; } // This method is automatically called by SObjectizer during agent's registration procedure. virtual void so_define_agent() override { // Subscription for only one signal. so_default_state().event< pong >( [this] { ++m_pongs; so_5::send< ping >( m_ponger ); } ); } SObjectizer Team, May 2017
  18. 18. Example Code (pinger agent, end): // This method is automatically called by SObjectizer just after successful registration. // Pinger uses this method to initiate message exchange. virtual void so_evt_start() override { // Sending signal by corresponding function. so_5::send< ping >( m_ponger ); } // This method is automatically called by SObjectizer just before deregistration of agent. virtual void so_evt_finish() override { // Sending result message by corresponding function. so_5::send< run_result >( // Receiver of the message. m_parent, // This will be forwarded to run_result's constructor. "pongs: " + std::to_string( m_pongs ) ); } private : const so_5::mbox_t m_parent; so_5::mbox_t m_ponger; unsigned int m_pongs = 0; }; SObjectizer Team, May 2017
  19. 19. Example Code (pоnger agent): // Ponger agent is very similar to pinger. But it hasn't so_evt_start method // because it will wait the first ping signal from the pinger. // It also does subscription in the constructor (SObjectizer allows definition // of subscriptions outside of so_define_agent method). class ponger : public so_5::agent_t { public : ponger(context_t ctx, so_5::mbox_t parent) : so_5::agent_t{ctx}, m_parent{std::move(parent)} { so_default_state().event< ping >( [this]{ ++m_pings; so_5::send< pong >( m_pinger ); } ); } void set_pinger_mbox( const so_5::mbox_t & mbox ) { m_pinger = mbox; } virtual void so_evt_finish() override { so_5::send< run_result >( m_parent, "pings: " + std::to_string( m_pings ) ); } private : const so_5::mbox_t m_parent; so_5::mbox_t m_pinger; unsigned int m_pings = 0; }; SObjectizer Team, May 2017
  20. 20. Example Code (parent agent, beginning): // Parent agent. // Creates pair of pinger/ponger agents, then limits their working time, // then handles their run results. class parent : public so_5::agent_t { private : // Time limit signal. struct stop : public so_5::signal_t {}; // Additional state for the agent. // This state means that the first result from children agents // has been received and that the parent expects the last one. const so_5::state_t st_first_result_got{ this }; // Result's accumulator. std::string m_results; public : parent( context_t ctx ) : so_5::agent_t{ ctx } {} SObjectizer Team, May 2017
  21. 21. Example Code (parent agent, continued-1): virtual void so_define_agent() override { // Arriving of time limit signal means that // child cooperation must be deregistered. so_default_state().event< stop >( [this] { so_environment().deregister_coop( // Name of cooperation for deregistration. "pinger_ponger", // The reason of deregistration, // this value means that deregistration is caused // by application logic. so_5::dereg_reason::normal ); } ); // NOTE: type of message is automatically deduced from // event handlers signatures. // First result will be received in default state. so_default_state().event( &parent::evt_first_result ); // But the second one will be received in next state. st_first_result_got.event( &parent::evt_second_result ); } SObjectizer Team, May 2017
  22. 22. Example Code (parent agent, continued-2): virtual void so_evt_start() { // Creation of child cooperation with pinger and ponger. so_5::introduce_child_coop( *this, // Parent of the new coop. "pinger_ponger", // Name of child coop. // Child cooperation will use active_obj dispatcher. // So pinger and ponger will work on the different working threads. so_5::disp::active_obj::create_private_disp( so_environment() )->binder(), [&]( so_5::coop_t & coop ) { // Filling the child cooperation. auto a_pinger = coop.make_agent< pinger >(so_direct_mbox()); auto a_ponger = coop.make_agent< ponger >(so_direct_mbox()); a_pinger->set_ponger_mbox( a_ponger->so_direct_mbox() ); a_ponger->set_pinger_mbox( a_pinger->so_direct_mbox() ); } ); // Limit the pinger/ponger exchange time. so_5::send_delayed< stop >( *this, std::chrono::seconds( 1 ) ); } SObjectizer Team, May 2017
  23. 23. Example Code (parent agent, end): private : // Event handler for the first result. void evt_first_result( const run_result & evt ) { m_results = evt.m_result + "; "; // State of the agent must be changed. this >>= st_first_result_got; } // Event handler for the next (and last) result. void evt_second_result( const run_result & evt ) { m_results += evt.m_result; // Show the results and finish work. std::cout << m_results << std::endl; // This is deregistration of the last live cooperation. // SO Environment will finish its work. so_deregister_agent_coop_normally(); } }; SObjectizer Team, May 2017
  24. 24. Example Code (main function): int main() { try { // Create SO Environment objects and run SO Run-Time inside it. so_5::launch( // SO Environment initialization routine. []( so_5::environment_t & env ) { // We must have the cooperation with just one agent inside it. // The name for the cooperation will be generated automatically. env.introduce_coop( []( so_5::coop_t & coop ) { // The single agent in the cooperation. coop.make_agent< parent >(); } ); } ); } catch( const std::exception & x ) { std::cerr << "Exception: " << x.what() << std::endl; } } SObjectizer Team, May 2017
  25. 25. Result: pongs: 1005040; pings: 1005041 Just about 2M messages per seconds with the exchange by a single message between two different threads (pinger and ponger work on different threads). Core i7 2.4GHz, 8GiB RAM, Win8.1 64-bit, Visual C++ 2013 64-bit SObjectizer Team, May 2017
  26. 26. Additional Information: Project’s home: Documentation: Forum: Google-group:!forum/sobjectizer Support: