SObjectizer  5.8
Loading...
Searching...
No Matches
so-5.5.16: New select functions for receive messages from several mchains

Since v.5.5.16 there are two new so_5::select functions which allow to receive and handle messages from several mchains.

The first variant of select takes a timeout and a list of mchains and message handlers for them:

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) {...}, [](const reply4 & r) {...}));

It checks the mchains and wait for no more than 500ms if all mchains are empty. If some mchain is not empty it extracts just one message from that mchain and tries to find an appropriate handler for it. If handler is found it is called. If a handler is not found then the message extracted will be thrown out without any processing.

If all mchains are empty even after the specified timeout then select will do nothing.

Simple form of select extract just one message from a mchain. Which non-empty mchain will be used for message extraction is not determined.

Please note that if there is just one non-empty mchain then simple select will return after extraction on just one message. This message could not be processed if there is no appropriate handler for it.

As with receive 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 unlimited waiting. The return from receive will be on arrival of any message. Or if the mchain is closed explicitly.

There is also 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. For example:

using namespace so_5;
mchain_t ch1 = env.create_mchain(...);
mchain_t ch2 = env.create_mchain(...);
// 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 is 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 explicitely.
select( from_all().handle_n( 3 ),
case_( ch1,
[]( const first_message_type & msg ) { ... },
[]( const second_message_type & msg ) { ... } ),
case_( ch2,
[]( const third_message_type & msg ) { ... },
handler< some_signal_type >( []{ ... ] ),
... ) );
// Receive and handle 3 messages.
// If there is no 3 messages in chains the select will wait
// no more that 200ms.
// A return from select will be after handling of 3 messages or
// if all mchains are closed explicitely, or if there is no messages
// for more than 200ms.
select( from_all().handle_n( 3 ).empty_timeout( milliseconds(200) ),
case_( ch1,
[]( const first_message_type & msg ) { ... },
[]( const second_message_type & msg ) { ... } ),
case_( ch2,
[]( const third_message_type & msg ) { ... },
handler< some_signal_type >( []{ ... ] ),
... ) );
// Receive all messages from mchains.
// If there is no message in any of mchains then wait no more than 500ms.
// A return from select will be after explicit close of all mchains
// or if there is no messages for more than 500ms.
select( from_all().empty_timeout( milliseconds(500) ),
case_( ch1,
[]( const first_message_type & msg ) { ... },
[]( const second_message_type & msg ) { ... } ),
case_( ch2,
[]( const third_message_type & msg ) { ... },
handler< some_signal_type >( []{ ... ] ),
... ) );
// Receve any number of messages from mchains but do waiting and
// handling for no more than 2s.
select( from_all().total_time( seconds(2) ),
case_( ch1,
[]( const first_message_type & msg ) { ... },
[]( const second_message_type & msg ) { ... } ),
case_( ch2,
[]( const third_message_type & msg ) { ... },
handler< some_signal_type >( []{ ... ] ),
... ) );
// Receve 1000 messages from chains but do waiting and
// handling for no more than 2s.
select( from_all().extract_n( 1000 ).total_time( seconds(2) ),
case_( ch1,
[]( const first_message_type & msg ) { ... },
[]( const second_message_type & msg ) { ... } ),
case_( ch2,
[]( const third_message_type & msg ) { ... },
handler< some_signal_type >( []{ ... ] ),
... ) );
Private part of message limit implementation.
Definition agent.cpp:33
mchain_select_params_t< mchain_props::msg_count_status_t::undefined > from_all()
Helper function for creation of mchain_select_params instance with default values.
mchain_select_result_t select(const mchain_select_params_t< Msg_Count_Status > &params, Cases &&... cases)
An advanced form of multi chain select.

Both select versions return an object of so_5::mchain_receive_result_t type. Methods of that object allow to get number of extracted and handled messages, and also the status of select operation.

It is possible to use a mchain in several select on different threads at the same time.

NOTE! A mchain can be used inside just one case_ statement in select. If the same mchain is used in several case_ statements then the behaviour of select is undefined. Please note also that select do not checks uniqueness of mchains in case_ statements (for performance reasons).