19#ifndef MTCORE_THREAD_SELECT_HPP
20#define MTCORE_THREAD_SELECT_HPP
55 template<SelectOption... Options>
88 if (res.is_success()) {
91 auto err = res.error().code;
112 template<Sender S,
typename Callback>
122 if (res.is_success()) {
126 auto err = res.error().code;
153 template<Sender S,
typename Callback>
179 template<
typename Clock,
typename Duration,
typename Callback>
195 static_assert(
is_select_option<BeforeOption<std::chrono::system_clock, std::chrono::nanoseconds, void (*)(void)>>,
196 "BeforeOption is invalid!");
204 template<
typename Clock,
typename Duration>
219 "BeforeOptionNoCallback is invalid!");
232 template<
typename Clock,
typename Duration,
typename Callback>
234 const Callback &callback) {
247 template<
typename Clock,
typename Duration>
262 template<
typename Rep,
typename Per,
typename Callback>
263 auto timeout(
const std::chrono::duration<Rep, Per> &tp,
const Callback &callback) {
264 return before(std::chrono::steady_clock::now() + tp, callback);
275 template<
typename Rep,
typename Per>
276 auto timeout(
const std::chrono::duration<Rep, Per> &tp) {
277 return before(std::chrono::steady_clock::now() + tp);
285 template<Receiver R,
typename Callback>
292 auto res =
channel.try_receive();
293 if (res.is_success()) {
315 template<Receiver R,
typename Callback>
321 template<SelectOption... Options>
325 concept SelectImpl =
requires(T &t,
const T &ct) {
326 { t.run_step() } -> std::same_as<Result<void, SelectErrors>>;
327 { ct.prevents_deadlock() } -> std::same_as<bool>;
328 { ct.skip() } -> std::same_as<bool>;
329 { t() } -> std::same_as<Result<void, SelectErrors>>;
335 template<SelectImpl T>
336 struct IsSelectImpl<T> : std::true_type {};
339 struct IsSelectImpl : std::false_type {};
342 constexpr bool is_select_impl = IsSelectImpl<T>::value;
356 [[nodiscard]]
bool skip() const noexcept {
return false; }
358 static_assert(impl::is_select_impl<Select<>>,
"Invalid select specialization");
367 template<SelectOption CurOption, SelectOption... Options>
377 auto res =
val.attempt();
378 if (res.is_success()) {
389 return next.run_step();
393 return (
val.prevents_deadlock() && !
skip()) ||
next.prevents_deadlock();
400 static_assert(impl::is_select_impl<Select<SendOptionNoCallback<Channel<int>>>>,
"Invalid select specialization");
402 static_assert(impl::is_select_impl<Select<SendOption<Channel<int>, void (*)(void)>>>,
403 "Invalid select specialization");
405 static_assert(impl::is_select_impl<Select<ReceiveOption<Channel<int>, void (*)(int)>>>,
406 "Invalid select specialization");
409 impl::is_select_impl<Select<BeforeOption<std::chrono::system_clock, std::chrono::nanoseconds, void (*)(void)>>>,
410 "Invalid select specialization");
413 impl::is_select_impl<Select<BeforeOptionNoCallback<std::chrono::system_clock, std::chrono::nanoseconds>>>,
414 "Invalid select specialization");
416 template<SelectOption... Options>
418 return Select<Options...>{opts...}();
422 template<SelectOption... Options>
424 while (sel.prevents_deadlock()) {
425 auto res = sel.run_step();
426 if (res.is_error()) {
434 std::this_thread::yield();
Checks if something qualifies as an option to a select statement Allows defining custom options and c...
SelectOptionErrors
Errors indicating control flow from a select option ATTEMPT_FAILED indicates to try the next option S...
SelectErrors
Errors for when a select statement fails SELECT_TIMEOUT and DEADLOCK_DETECTED are the only ones which...
Success< void > success()
Creates a successful void Result object.
Error< Underlying > error(Underlying err)
Creates an error.
SendOption< S, Callback > send_to(S &to, typename S::Message msg, const Callback &callback)
Creates a select case which will try to send a message to a sender Option will call a callback on suc...
ReceiveOption< R, Callback > receive_from(R &from, const Callback &callback)
Creates a receive option for select which will execute when a message is ready.
Result< void, SelectErrors > select(Options... opts)
Creates a "select statement" similar to Go's select statement, except this statement runs on thread-b...
BeforeOption< Clock, Duration, Callback > before(const std::chrono::time_point< Clock, Duration > &tp, const Callback &callback)
The before option will timeout a select if an option is not hit before the target time point.
auto timeout(const std::chrono::duration< Rep, Per > &tp, const Callback &callback)
Does a timeout relative to current time (e.g.
constexpr bool is_select_option
Checks if a type can be used in a select statement as an option.
constexpr bool has_closed_error
Checks if an error type has a recognized closed error.
Thread-related namespace The methods and classes provided by this class are thread-safe Classes and m...
Represents a Result that may have an error (error code) or a success value A type of "void" means the...
Option to add a timeout on select to ensure a path runs before a timeout If the timeout is hit,...
bool prevents_deadlock() const noexcept
Result< void, SelectOptionErrors > attempt()
std::chrono::time_point< Clock, Duration > time_point
Option to add a timeout on select to ensure a path runs before a timeout If the timeout is hit,...
bool prevents_deadlock() const noexcept
Result< void, SelectOptionErrors > attempt()
std::chrono::time_point< Clock, Duration > time_point
Select option to receive a message and calls a callback on receive.
Result< void, SelectOptionErrors > attempt()
typename R::Message Message
bool prevents_deadlock() const noexcept
bool skip() const noexcept
Result< void, SelectErrors > operator()()
Result< void, SelectErrors > run_step()
bool prevents_deadlock() const noexcept
Select(CurOption val, Options... vals)
Select< Options... > next
bool skip() const noexcept
Result< void, SelectErrors > run_step()
Result< void, SelectErrors > operator()()
bool prevents_deadlock() const noexcept
Underlying type for a select statement Use the "select" method directly for instantiation.
Select option to send a message without calling a callback on send.
typename S::Message Message
bool prevents_deadlock() const noexcept
Checks if option is still valid (invalidates on channel close)
Result< void, SelectOptionErrors > attempt()
Select option to send a message.
Result< void, SelectOptionErrors > attempt()
typename S::Message Message
bool prevents_deadlock() const noexcept
Checks if option is still valid (invalidates on channel close)