-
Notifications
You must be signed in to change notification settings - Fork 46
v.5.6.1
This page describes changes and new features of v.5.6.1.
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.
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.