Skip to content

v.5.6.1

eao197 edited this page Sep 5, 2019 · 3 revisions

This page describes changes and new features of v.5.6.1.

Extensible-select is added

There was an issue with select() function in the previous versions of SObjectizer: select() or prepare_select() required that list of mchains to listen was known at the compile time. For example, this code was OK:

void wait_for_ack(so_5::mchain_t ch1, so_5::mchain_t ch2, so_5::mchain_t ch3) {
   so_5::select(so_5::from_all().handle_n(1),
      case_(ch1, [](ack) {...}),
      case_(ch2, [](ack) {...}),
      case_(ch3, [](ack) {...}));
   ...
}

but that was imposible:

void wait_for_ack(const std::vector<so_5::mchain_t> & chains) {
   ? // How to pass a case for every chain from chains to select()?
}

Extensible-select is introduced in v.5.6.1. That feature allows to solve the problem shown above that way:

void wait_for_ack(const std::vector<so_5::mchain_t> & chains) {
   auto sel = so_5::make_extensible_select(so_5::from_all().handle_n(1));
   for(auto & ch : chains)
      so_5::add_select_cases(sel, case_(ch, [](ack) {...}));
   so_5::select(sel);
}

NOTE. Extensible-select object returned by make_extensible_select is thread-safe. It means that add_select_cases can be called from the different threads at the same time. But if that object is passed to select() function it can't be modified or passed to another call to select() until the first select() finishes its work.

Refactored implementation of prepared-select

A problem in the implementation of prepared-select was found: the usage of prepared-select instance in several calls to select() at the same time was allowed and could lead to undefined behavior. For example, in that scenario:

auto sel = so_5::prepare_select(so_5::from_all().handle_n(10),
   case_(ch1, ...),
   case_(ch2, ...),
   ...);
std::thread worker_one([&] {
   so_5::select(sel); // One parallel call to select().
   ...
});
std::thread worker_two([&] {
   so_5::select(sel); // Second parallel call to select().
   ...
});

parallel calls to select() can lead to data damages because of data-races or even to dereferencing of dangling pointers.

Since v.5.6.1 simultaneous calls to select() on the same prepared-select object are controlled. If a new call to select() is detected while the previous call to select() is still active then an exception is thrown.

Clone this wiki locally