New helper function so_5::auto_close_mchains has been added in v.5.5.16. It helps to close some mchains at scope exit.
When mchains are used for inter thread communication special care must be taken because there could be deadlocks. For example let see the simplest case:
{
auto ch = create_mchain(env);
thread child{ [ch]{
receive(from(ch), [](const some_task & t) {...});
} };
while(has_tasks())
{
...
send<some_task>(ch, ...);
}
child.join();
}
Private part of message limit implementation.
This is an error in this example: do_something will not return. It is becase child thread will never finished. Because mchain ch will not be closed explicitely.
It easy to fix that example:
while(has_tasks())
{
...
send<some_task>(ch, ...);
}
close_retain_content(ch);
child.join();
But there could be more complex cases related to exception safety. If an exception is thrown after construction of child but before call to close_retain_content there could be a deadlock (see above).
To make this code exception safe we need two helpers: one of them should close chain, another should call join for threads. Something like that:
class auto_closer {
public :
~auto_closer() { close_retain_content(ch_); }
};
class auto_joiner {
thread & thr_;
public :
auto_joiner(thread & thr) : thr_{thr} {}
~auto_joiner() { if(thr_.joinable()) thr_.close(); }
};
With the help of these classes we can make do_something more exception safe:
{
auto ch = create_mchain(env);
thread child{ [ch]{
receive(from(ch), [](const some_task & t) {...});
} };
auto_joiner child_joiner{ child };
auto_closer ch_closer{ ch };
while(has_tasks())
{
...
send<some_task>(ch, ...);
}
}
But writting ad-hoc classes like auto_closer is a boring and error-prone tasks. Helper function so_5::auto_close_mchains do it for you:
{
auto ch = create_mchain(env);
thread child{ [ch]{
receive(from(ch), [](const some_task & t) {...});
} };
auto_joiner child_joiner{ child };
while(has_tasks())
{
...
send<some_task>(ch, ...);
}
}
mchain_auto_close_details::auto_closer_t< sizeof...(Tail) > auto_close_mchains(mchain_props::close_mode_t close_mode, Tail &&... tail)
Helper function for creation of automatic closer of mchains.
Function auto_close_mchains returns object very similar to auto_closer shown above. The destructor of that object will close all mchains passed to auto_close_mchains. It is possible to pass several mchains to one call of auto_close_mchains:
auto command_ch = create_mchain(env);
auto reply_ch = create_mchain(env);
auto status_ch = create_mchain(env);
auto log_ch = create_mchain(env);
auto ch_closer = auto_close_mchains(mchain_props::close_mode_t::drop_content,
command_ch, reply_ch, status_ch, log_ch);
...
Because usage of auto_close_mchains is verbose there are two shorthands: auto_close_retain_content and auto_close_drop_content. So instead of writting:
auto ch_closer = auto_close_mchains(mchain_props::close_mode_t::drop_content,
command_ch, reply_ch, status_ch, log_ch);
it is possible to write:
auto ch_closer = auto_close_drop_content(command_ch, reply_ch, status_ch, log_ch);