67
Dive into SObjectizer-5.5 SObjectizer Team, May 2017 Ninth Part: Message Chains (at v.5.5.19)

Dive into SObjectizer 5.5. Ninth Part: Message Chains

Embed Size (px)

Citation preview

Page 1: Dive into SObjectizer 5.5. Ninth Part: Message Chains

Dive into SObjectizer-5.5

SObjectizer Team, May 2017

Ninth Part: Message Chains(at v.5.5.19)

Page 2: Dive into SObjectizer 5.5. Ninth Part: Message Chains

This is the next part of the series of presentations with deep introduction into features of SObjectizer-5.5.

This part is dedicated to message chains feature.

The feature is relatively new.It was introduced in v.5.5.13.

SObjectizer Team, May 2017

Page 4: Dive into SObjectizer 5.5. Ninth Part: Message Chains

The main purpose of message chains is to simplify interaction between SObjectizer- and non-SObjectizer parts of application.

SObjectizer Team, May 2017

Page 5: Dive into SObjectizer 5.5. Ninth Part: Message Chains

It is pretty simple to send a message from a non-SObjectizer-part to a SObjectizer-part of an application: a message or signal can be sent to some mbox in a usual way.

However, there was no a ready to use way to receive a reply message or signal back. Because in non-SObjectizer-part there couldn't be an entity behind mbox until v.5.5.13.

Then message chains (or mchains) were added...

SObjectizer Team, May 2017

Page 6: Dive into SObjectizer 5.5. Ninth Part: Message Chains

Currently, it is possible to send a message or a signal to a mchain from SObjectizer-part and receive and handle it in non-SObjectizer-part via receive function.

Let's see how it looks like...

SObjectizer Team, May 2017

Page 7: Dive into SObjectizer 5.5. Ninth Part: Message Chains

The agent which receives requests and sends replies:class request_processor final : public so_5::agent_t{ const so_5::mchain_t m_reply_to;public : request_processor( context_t ctx, so_5::mchain_t reply_to ) : so_5::agent_t{ ctx }, m_reply_to{ std::move(reply_to) } { // Requests will be sent from "handler" mbox. so_subscribe( so_environment().create_mbox( "handler" ) ) .event( [&]( const request & msg ) { ... // Some request handling // Sending a reply back. so_5::send< reply >( m_reply_to, ... ); } ); ... } ...};

SObjectizer Team, May 2017

Page 8: Dive into SObjectizer 5.5. Ninth Part: Message Chains

The non-SObjectizer-part which sends requests and receives responses:so_5::wrapped_env_t sobj;

// mchain for replies.// Simplest mchain without any limitations.auto reply_ch = create_mchain( sobj );// Launch request_processor and pass reply chain to it.make_and_launch_request_processor( sobj, reply_ch );

// Sending requests and handling replies.while( has_something_to_do() ) { // Send new requests ordinary way. so_5::send< request >( sobj.environment().create_mbox( "handler" ), ... ); // Receive and handle response. receive( reply_ch, so_5::infinite_wait, []( const reply & msg ) { ... } );}

SObjectizer Team, May 2017

Page 10: Dive into SObjectizer 5.5. Ninth Part: Message Chains

The mchain_t type is similar to mbox_t.

It is an alias for a smart intrusive pointer to abstract_message_chain_t.

It means that mchain created by create_mchain will be destroyed automatically right after destruction of the last mchain_t object pointing to it.

SObjectizer Team, May 2017

Page 12: Dive into SObjectizer 5.5. Ninth Part: Message Chains

There are two types of mchains:

1. Unlimited mchains. The mchain has no limitation for the number of messages to be stored inside mchain. This number is limited only by the amount of available memory and by common sense of developer.

2. Limited mchains. The mchain has a strict limit for the number of messages. It is just impossible to push yet another message into full size-limited mchain.

SObjectizer Team, May 2017

Page 13: Dive into SObjectizer 5.5. Ninth Part: Message Chains

The type of mchain is specified at creation of mchain instance. Once created, the type of mchain cannot be changed.

The type of mchain is specified by the content of mchain_params_t instance passed to environment_t::create_mchain method.

There are several helper functions which simplify creation of mchains of various types...

SObjectizer Team, May 2017

Page 14: Dive into SObjectizer 5.5. Ninth Part: Message Chains

Creation of an unlimited mchain:

so_5::mchain_t m1 = env.create_mchain(so_5::make_unlimited_mchain_params());

// Or via free helper function.so_5::environment_t & env = ...;so_5::mchain_t m1 = create_mchain(env);

// Or via another helper function.so_5::wrapped_env_t sobj;so_5::mchain_t m1 = create_mchain(sobj);

SObjectizer Team, May 2017

Page 15: Dive into SObjectizer 5.5. Ninth Part: Message Chains

Creation of a size-limited mchain without waiting for attempt of pushing new message to the full mchain:

so_5::mchain_t m2 = env.create_mchain( so_5::make_limited_without_waiting_mchain_params( // Capacity of mchain's message queue. 200, // mchain's message queue will grow and shrink dynamically. so_5::mchain_props::memory_usage_t::dynamic, // Drop new message if mchain is full. so_5::mchain_props::overflow_reaction_t::drop_newest));

// Or via free helper function.so_5::mchain_t m2 = create_mchain(env, 200, so_5::mchain_props::memory_usage_t::dynamic, so_5::mchain_props::overflow_reaction_t::drop_newest);

SObjectizer Team, May 2017

Page 16: Dive into SObjectizer 5.5. Ninth Part: Message Chains

Creation of a size-limited mchain with waiting for attempt of pushing new message to full mchain:so_5::mchain_t m3 = env.create_mchain( so_5::make_limited_with_waiting_mchain_params( // Capacity of mchain's message queue. 200, // mchain's message queue will use preallocated fixed size storage so_5::mchain_props::memory_usage_t::preallocated, // New message will be dropped if mchain is full after a timeout. so_5::mchain_props::overflow_reaction_t::drop_newest, // A time for waiting for a free room in mchain if the mchain is full. std::chrono::milliseconds(500)));

// Or via free helper function.so_5::mchain_t m3 = create_mchain(env, std::chrono::milliseconds(500), 200, so_5::mchain_props::memory_usage_t::preallocated, so_5::mchain_props::overflow_reaction_t::drop_newest);

SObjectizer Team, May 2017

Page 17: Dive into SObjectizer 5.5. Ninth Part: Message Chains

More About Size-Limited mchains

SObjectizer Team, May 2017

Page 18: Dive into SObjectizer 5.5. Ninth Part: Message Chains

Size-limited mchains are quite different from size-unlimited mchains:

a size-limited mchain can't contain more messages than the max capacity of the mchain.

So, there should be some reaction for attempt to add another message to full mchain.

SObjectizer Team, May 2017

Page 19: Dive into SObjectizer 5.5. Ninth Part: Message Chains

There are size-limited mchains which will wait for some time for attempt of pushing new message to the full mchain.

If there is a free space in the mchain after that waiting then the new message will be stored in the mchain.

Otherwise, the appropriate overload reaction will be performed.

SObjectizer Team, May 2017

Page 20: Dive into SObjectizer 5.5. Ninth Part: Message Chains

Also, there are size-limited mchains without any waiting time for the full mchain.

If there is no free space in the mchain then the appropriate overload reaction will be performed immediately.

SObjectizer Team, May 2017

Page 21: Dive into SObjectizer 5.5. Ninth Part: Message Chains

There are four overload reactions which can be selected for the mchain at the moment of its creation:

1. Dropping new message. It means that the new message will be simply ignored.

2. Removing the oldest message from the mchain. It means that the oldest message in the mchain will be removed and it will not be processed.

3. Throwing an exception. The exception with error code rc_msg_chain_overflow will be raised as a result of attempt of pushing a new message to the full mchain.

4. Aborting the whole application by calling std::abort().

SObjectizer Team, May 2017

Page 22: Dive into SObjectizer 5.5. Ninth Part: Message Chains

Another important property which should be specified for size-limited mchain at the creation time is the type of memory usage.

The memory for storing messages inside mchain can be used dynamically: it will be allocated when mchain grows and deallocated when mchain shrinks.

Likewise, the memory for mchain can be preallocated and there will be a fixed-size buffer for messages. The buffer size will not change during growth and shrinking of the mchain.

SObjectizer Team, May 2017

Page 23: Dive into SObjectizer 5.5. Ninth Part: Message Chains

All these properties of size-limited mchains are controlled by contents of the corresponding mchain_params_t:

so_5::mchain_t chain = env.create_mchain( so_5::make_limited_with_waiting_mchain_params( // No more than 200 messages in the mchain. 200, // Memory will be preallocated. so_5::mchain_props::memory_usage_t::preallocated, // An exception will be thrown if there is no free room in the mchain. so_5::mchain_props::overflow_reaction_t::throw_exception, // But before throwing an exception there will be 500ms timeout std::chrono::milliseconds(500)));

SObjectizer Team, May 2017

Page 24: Dive into SObjectizer 5.5. Ninth Part: Message Chains

Receiving And Handling Messages From mchains

SObjectizer Team, May 2017

Page 25: Dive into SObjectizer 5.5. Ninth Part: Message Chains

so_5::receive function which allows us to receive and handle messages from mchain has two variants.

SObjectizer Team, May 2017

Page 26: Dive into SObjectizer 5.5. Ninth Part: Message Chains

The first variant of receive takes mchain_t, timeout and the list of message handlers:

so_5::mchain_t ch = env.create_mchain(...);...receive(ch, std::chrono::milliseconds(500), [](const reply1 & r) {...}, [](const reply2 & r) {...}, ... [](const replyN & r) {...});

Note: because of ADL there is no need to write a call to receive as so_5::receive. Appropriate receive version will be found in so_5 namespace automatically.

SObjectizer Team, May 2017

Page 27: Dive into SObjectizer 5.5. Ninth Part: Message Chains

What does this call do?receive(ch, std::chrono::milliseconds(500), [](const reply1 & r) {...}, ... [](const replyN & r) {...});

It checks the mchain and waits for no more than 500ms if the mchain is empty.

If the mchain is not empty it extracts just one message from the mchain and tries to find an appropriate handler for it. If the handler is found it is called. If the handler is not found then the extracted message will be thrown out without any processing.

SObjectizer Team, May 2017

Page 28: Dive into SObjectizer 5.5. Ninth Part: Message Chains

If the mchain is empty even after the specified timeout then receive does nothing.

There are two special values which can be used as timeout:

● value so_5::no_wait specifies zero timeout. It means that receive will not wait if the mchain is empty;

● value so_5::infinite_wait specifies endless waiting. The return from receive will be on arrival of any message. Or if the mchain is closed explicitly.

SObjectizer Team, May 2017

Page 29: Dive into SObjectizer 5.5. Ninth Part: Message Chains

The second variant of receive is much more complicated:

receive( // Extract no more than 1000 messages from queue. // Take no more than 2s of total extraction and processing time. from(chain).extract_n( 1000 ).total_time( seconds(2) ), [](const reply1 & msg) {...}, [](const reply2 & msg) {...}, ... [](const reply3 & msg) {...} );

SObjectizer Team, May 2017

Page 30: Dive into SObjectizer 5.5. Ninth Part: Message Chains

The advanced version of receive allows us to specify a bunch of exit-conditions. For example:

● handle no more than N messages;● extract no more than N messages (number of extracted

messages can be larger than the number of handled messages);

● max waiting time in case of an empty mchain;● max processing time for the whole receive;● some external condition fulfilled.

SObjectizer Team, May 2017

Page 31: Dive into SObjectizer 5.5. Ninth Part: Message Chains

Both receive versions return an object of mchain_receive_result_t type.

Methods of that object allow us to get the number of extracted and handled messages, and also the status of receive operation:// Sending requests and handling replies.while( has_something_to_do() ) { // Send new requests ordinary way. so_5::send< request >( sobj.environment().create_mbox( "handler" ), ... ); // Receive and handle response. auto r = receive( from(reply_ch).empty_timeout( std::chrono::seconds(1) ), []( const reply & msg ) { ... } ); if( !r.handled() ) ... // No reply arrived within 1s.}

SObjectizer Team, May 2017

Page 32: Dive into SObjectizer 5.5. Ninth Part: Message Chains

The receive functions family allows to receive and handle messages from just one mchain.

But since v.5.5.16 there is select functions family which allows to receive and handle messages from several mchains...

SObjectizer Team, May 2017

Page 33: Dive into SObjectizer 5.5. Ninth Part: Message Chains

The simplest variant of select is like the simplest variant of receive: it extracts just one message.

so_5::mchain_t ch1 = env.create_mchain(...);so_5::mchain_t ch2 = env.create_mchain(...);so_5::mchain_t ch3 = env.create_mchain(...);...so_5::select(std::chrono::milliseconds(500), case_(ch1, [](const reply1 & r) {...}), case_(ch2, [](const reply2 & r) {...}), case_(ch2, [](const reply3 & r) {...}));

The return from select will be on extraction of one message from any of (ch1, ch2, ch3) mchains or if all mchains are empty within 500ms.

SObjectizer Team, May 2017

Page 34: Dive into SObjectizer 5.5. Ninth Part: Message Chains

Also, there is more advanced version of select which can receive and handle more than one message from mchains.

It receives a so_5::mchain_select_params_t objects with list of conditions and returns control if any of those conditions becomes true...

SObjectizer Team, May 2017

Page 35: Dive into SObjectizer 5.5. Ninth Part: Message Chains

For example:// Receive and handle 3 messages.// It could be 3 messages from ch1. Or 2 messages from ch1 and 1 message// from ch2. Or 1 message from ch1 and 2 messages from ch2. And so on...// If there are no 3 messages in mchains the select will wait infinitely. A return from select// will be after handling of 3 messages or if all mchains are closed explicitly.select(from_all().handle_n(3), case_( ch1, handler1_1, handler1_2, ...), case_( ch2, handler2_1, handler2_2, ...));

// Receive and handle 3 messages.// If there are no 3 messages in chains the select will wait no more than 200ms.// A return from select will be after handling of 3 messages or if all mchains are closed// explicitly, or if there are no messages for more than 200ms.select(from_all().handle_n(3).empty_timeout(milliseconds(200)), case_( ch1, handler1_1, handler1_2, ...), case_( ch2, handler2_1, handler2_2, ...));

SObjectizer Team, May 2017

Page 36: Dive into SObjectizer 5.5. Ninth Part: Message Chains

The advanced version of select allows to specify a bunch of exit-conditions. For example:

● handle no more than N messages;● extract no more than N messages (number of extracted

messages can be larger than the number of handled messages);

● max waiting time in case of empty mchains;● max processing time for the whole select;● some external condition fulfilled.

SObjectizer Team, May 2017

Page 37: Dive into SObjectizer 5.5. Ninth Part: Message Chains

The advanced version of select is very similar to advanced version of receive. In fact almost all exit conditions for advanced select are just twins for exit conditions of advanced receive.

But select has yet another exit condition: select finishes its work if all mchains become closed.

SObjectizer Team, May 2017

Page 38: Dive into SObjectizer 5.5. Ninth Part: Message Chains

Both select versions return an object of mchain_receive_result_t type.

Methods of that object allow us to get the number of extracted and handled messages, and also the status of receive operation.

If no one message has been extracted because all mchains become closed then select returns extraction_status_t::chain_closed value as status of select operation.

SObjectizer Team, May 2017

Page 39: Dive into SObjectizer 5.5. Ninth Part: Message Chains

mchains Are MPMC Queues

SObjectizer Team, May 2017

Page 40: Dive into SObjectizer 5.5. Ninth Part: Message Chains

Since v.5.5.16 mchains are implemented as Multi-Producer and Multi-Consumer queues.

It means that it is possible to use the same mchain in parallel calls to several receive and select on different threads.

This feature can be used for implementation of very simple load-balancing scheme...

SObjectizer Team, May 2017

Page 41: Dive into SObjectizer 5.5. Ninth Part: Message Chains

An example of a very simple load-balancing scheme:void worker_thread(so_5::mchain_t ch) { // Handle all messages until mchain will be closed. receive(from(ch), handler1, handler2, handler3, ...);}...// Message chain for passing messages to worker threads.auto ch = create_mchain(env);// Worker threads.thread worker1{worker_thread, ch};thread worker2{worker_thread, ch};thread worker3{worker_thread, ch};auto thr_joiner = auto_join(worker1, worker2, worker3);// Send messages to workers.while(has_some_work()) { so_5::send< some_message >(ch, ...); ...}// Close chain and finish worker threads.close_retain_content(ch);

SObjectizer Team, May 2017

Page 43: Dive into SObjectizer 5.5. Ninth Part: Message Chains

Message handlers which are passed to receive and select functions family must be lambda-functions or functional objects with the following format:

return_type handler( const message_type& );return_type handler( message_type );return_type handler( const so_5::mhood_t<message_type>& );return_type handler( so_5::mhood_t<message_type> );return_type handler( so_5::mhood_t<so_5::mutable_msg<message_type>> );return_type handler( so_5::mutable_mhood_t<message_type> );

SObjectizer Team, May 2017

Page 44: Dive into SObjectizer 5.5. Ninth Part: Message Chains

Some examples of handlers prototypes:

struct classical_message : public so_5::message_t { ... };struct user_message { ... };...receive(chain, so_5::infinite_wait, [](const classical_message & m) {...}, [](const user_message & m) {...}, [](const int & m) {...}, [](long m) {...});

SObjectizer Team, May 2017

Page 45: Dive into SObjectizer 5.5. Ninth Part: Message Chains

The handler for signal of type signal_type can be created via using so_5::handler<signal_type>() function:

struct stopped : public so_5::signal_t {};struct waiting : public so_5::signal_t {};...receive(chain, so_5::infinite_wait, [](const classical_message & m) {...}, [](const user_message & m) {...}, so_5::handler<stopped>( []{...} ), so_5::handler<waiting>( []{...} ));

SObjectizer Team, May 2017

Page 46: Dive into SObjectizer 5.5. Ninth Part: Message Chains

If so_5::mhood_t<T> message wrapper is used the type T can be the type of message or signal:

struct check_status : public so_5::signal_t {};struct reconfig { std::string config_file; };...receive(chain, so_5::infinite_wait, [](const mhood_t<reconfig> & msg) {...}, [](mhood_t<check_status>) {...}, ... );

SObjectizer Team, May 2017

Page 47: Dive into SObjectizer 5.5. Ninth Part: Message Chains

The most important thing about message/signal handlers for receive and select/case_ functions:

All message handlers must handle different message types. It is an error if some handlers are defined for the same message type.

SObjectizer Team, May 2017

Page 48: Dive into SObjectizer 5.5. Ninth Part: Message Chains

Usage Of mchains With Send Functions

SObjectizer Team, May 2017

Page 49: Dive into SObjectizer 5.5. Ninth Part: Message Chains

All traditional send-functions like send, send_delayed and send_periodic work with mchains in the same way as they work with mboxes.

SObjectizer Team, May 2017

Page 50: Dive into SObjectizer 5.5. Ninth Part: Message Chains

It allows us to write the code in a traditional way:

// Sending a message.so_5::send<my_message>(ch, ... /* some args for my_message's constructor */);

// Sending a delayed message.so_5::send_delayed<my_message>(ch, std::chrono::milliseconds(200), ... /* some args for my_message's constructor */);

// Sending a periodic message.auto timer_id = so_5::send_periodic<my_message>(ch, std::chrono::milliseconds(200), std::chrono::milliseconds(250), ... /* some args for my_message's constructor */);

SObjectizer Team, May 2017

Page 51: Dive into SObjectizer 5.5. Ninth Part: Message Chains

The functions for performing service request, request_value and request_future, work with mchains too.

It means that agent can make a service request to non-SObjectizer part of an application and receive the result of that request as usual.

SObjectizer Team, May 2017

Page 52: Dive into SObjectizer 5.5. Ninth Part: Message Chains

Service request initiated by an agent:

// Somewhere in SObjectizer part of an application...class worker : public so_5::agent_t { const so_5::mchain_t m_request_ch; ... void some_event_handler() { auto f = so_5::request_future<response, request>(m_request_ch, ... /* some args for request's constructor */); ... handle_response(f.get()); }};...// Somewhere in non-SObjectizer part of an application...const so_5::mchain_t request_ch = ...;receive( from(request_ch).handle_n(1000), [](const request & req) -> response {...}, ... );

SObjectizer Team, May 2017

Page 54: Dive into SObjectizer 5.5. Ninth Part: Message Chains

There is a method abstract_message_chain_t::as_mbox which can represent mchain as almost ordinary mbox.

This method returns mbox_t and the mbox can be used for sending messages and performing service request to the mchain.

SObjectizer Team, May 2017

Page 55: Dive into SObjectizer 5.5. Ninth Part: Message Chains

Method as_mbox can be useful if there is a necessity to hide the fact of mchain existence.

For example, an agent inside SObjectizer’s part of an application can receive mbox and think that there is another agent on the opposite side...

SObjectizer Team, May 2017

Page 56: Dive into SObjectizer 5.5. Ninth Part: Message Chains

mchain as mbox in SObjectizer-part of an application:class request_processor final : public so_5::agent_t{ const so_5::mbox_t m_reply_to;public : request_processor( context_t ctx, so_5::mbox_t reply_to ) : so_5::agent_t{ ctx }, m_reply_to{ std::move(reply_to) } { // Requests will be sent from "handler" mbox. so_subscribe( so_environment().create_mbox( "handler" ) ) .event( [&]( const request & msg ) { ... // Some request handling // Sending a reply back. so_5::send< reply >( m_reply_to, ... ); } ); ... } ...};

SObjectizer Team, May 2017

Page 57: Dive into SObjectizer 5.5. Ninth Part: Message Chains

mchain as mbox in non-SObjectizer-part of an application:so_5::wrapped_env_t sobj;

// mchain for replies.// Simplest mchain without any limitations.auto reply_ch = create_mchain( sobj );// Launch request_processor and pass reply mchain to it.// mchain will be represented as mbox.make_and_launch_request_processor( sobj, reply_ch->as_mbox() );

// Sending requests and handling replies.while( has_something_to_do() ) { // Send new requests in an ordinary way. so_5::send< request >( sobj.environment().create_mbox( "handler" ), ... ); // Receive and handle response. receive( reply_ch, so_5::infinite_wait, []( const reply & msg ) { ... } );}

SObjectizer Team, May 2017

Page 58: Dive into SObjectizer 5.5. Ninth Part: Message Chains

The only difference between ordinary mbox created by environment_t::create_mbox and mbox created by as_mbox is that the second doesn’t allow to create subscriptions on it.

It means that agent request_processor from the example above can't subscribe its event handlers to messages from m_reply_to.

SObjectizer Team, May 2017

Page 59: Dive into SObjectizer 5.5. Ninth Part: Message Chains

Usage Of mchains For Programming In CSP Style

SObjectizer Team, May 2017

Page 60: Dive into SObjectizer 5.5. Ninth Part: Message Chains

mchains can be used for development of multithreaded applications based on SObjectizer even without agents.

Threads can interact with each other by means of mchains in CSP* style.

One thread can send messages to the mchain via ordinary send function. Another thread can receive and handle them via receive function.

SObjectizer Team, May 2017* https://en.wikipedia.org/wiki/Communicating_sequential_processes

Page 61: Dive into SObjectizer 5.5. Ninth Part: Message Chains

Let's see how concurrent HelloWorld example looks like in Go language...

...and in C++ with SObjectizer's mchains.

SObjectizer Team, May 2017

Page 62: Dive into SObjectizer 5.5. Ninth Part: Message Chains

SObjectizer Team, May 2017

Go version (code before main):package main

import "fmt"

C++ version (code before main):#include <iostream>#include <thread>

#include <so_5/all.hpp>

using namespace std;using namespace std::literals;using namespace so_5;

template< typename T >void operator<<( mchain_t & to, T && o ) { send< T >( to, forward<T>(o) );}

template< typename T >void operator>>( mchain_t & from, T & o ) { receive(from, infinite_wait, [&o]( const T & msg ) { o = msg; });}

Please note that SObjectizer does not provide shorthands like Go's <- operator and that’s why we need to define similar operators << and >> by hand.

Page 63: Dive into SObjectizer 5.5. Ninth Part: Message Chains

SObjectizer Team, May 2017

Go version (function main):func main() { sayHello := make(chan string) sayWorld := make(chan string) quitter := make(chan string)

go func() { for i := 0; i < 1000; i++ { fmt.Print("Hello ") sayWorld <- "Do it" <-sayHello } sayWorld <- "Quit" }()

go func() { for { var reply string reply = <-sayWorld if (reply == "Quit") { break } fmt.Print("World!\n") sayHello <- "Do it" } quitter <- "Done" }()

<-quitter}

C++ version (function main):int main() { wrapped_env_t sobj;

auto say_hello = create_mchain( sobj ); auto say_world = create_mchain( sobj );

thread hello{ [&] { string reply; for( int i = 0; i != 1000; ++i ) { cout << "Hello "; say_world << "Do it"s; say_hello >> reply; } say_world << "Quit"s; } };

thread world{ [&] { for(;;) { string reply; say_world >> reply; if( "Quit" == reply ) break; cout << "World" << endl; say_hello << "Do it"s; } } };

auto_join(hello, world);}

Page 65: Dive into SObjectizer 5.5. Ninth Part: Message Chains

mchains are relatively new addition to SObjectizer. They add an easy way of communication between SObjectizer- and non-SObjectizer-parts of an applications.

Likewise, mchains provide another way of solving producer-consumer problem. For example, size-limited mchains can be used for implementation of new mechanisms of overload control.

It is worth noting that they allow us to write multithreaded applications in CSP style without using agents.

SObjectizer Team, May 2017

Page 66: Dive into SObjectizer 5.5. Ninth Part: Message Chains

Thus, mchains can lead to new ways of writing SObjectizer-based programs.

Most likely, functionality of mchains will be extended in the future versions of SObjectizer.

This presentation should not be considered as a comprehensive guide to SObjectizer's mchains. For more information on mchains please see the corresponding Wiki section.

SObjectizer Team, May 2017

Page 67: Dive into SObjectizer 5.5. Ninth Part: Message Chains

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

Support: https://stiffstream.com