diff --git a/include/ircd/ctx/ctx.h b/include/ircd/ctx/ctx.h index 23c97d67c..f7e1d75e6 100644 --- a/include/ircd/ctx/ctx.h +++ b/include/ircd/ctx/ctx.h @@ -79,6 +79,8 @@ namespace ircd::ctx #include "prof.h" #include "this_ctx.h" +#include "wait.h" +#include "sleep.h" #include "stack_usage_assertion.h" #include "slice_usage_warning.h" #include "syscall_usage_warning.h" diff --git a/include/ircd/ctx/sleep.h b/include/ircd/ctx/sleep.h new file mode 100644 index 000000000..d0a2bcf9f --- /dev/null +++ b/include/ircd/ctx/sleep.h @@ -0,0 +1,39 @@ +// The Construct +// +// Copyright (C) The Construct Developers, Authors & Contributors +// Copyright (C) 2016-2020 Jason Volk +// +// Permission to use, copy, modify, and/or distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice is present in all copies. The +// full license for this software is available in the LICENSE file. + +#pragma once +#define HAVE_IRCD_CTX_SLEEP_H + +namespace ircd::ctx { inline namespace this_ctx +{ + // Ignores notes. Throws if interrupted. + void sleep_until(const system_point &tp); + template void sleep(const duration &); + void sleep(const int &secs); +}} + +/// This overload matches ::sleep() and acts as a drop-in for ircd contexts. +/// interruption point. +inline void +ircd::ctx::this_ctx::sleep(const int &secs) +{ + sleep(seconds(secs)); +} + +/// Yield the context for a period of time and ignore notifications. sleep() +/// is like wait() but it only returns after the timeout and not because of a +/// note. +/// interruption point. +template +void +ircd::ctx::this_ctx::sleep(const duration &d) +{ + sleep_until(system_clock::now() + d); +} diff --git a/include/ircd/ctx/this_ctx.h b/include/ircd/ctx/this_ctx.h index 389f166c1..c9cc01db5 100644 --- a/include/ircd/ctx/this_ctx.h +++ b/include/ircd/ctx/this_ctx.h @@ -12,33 +12,15 @@ #define HAVE_IRCD_CTX_THIS_CTX_H /// Interface to the currently running context -namespace ircd::ctx { -inline namespace this_ctx +namespace ircd::ctx { inline namespace this_ctx { struct ctx &cur() noexcept; ///< Assumptional reference to *current const uint64_t &id() noexcept; // Unique ID for cur ctx string_view name() noexcept; // Optional label for cur ctx ulong cycles() noexcept; // misc profiling related bool interruption_requested() noexcept; // interruption(cur()) - void interruption_point(); // throws if interruption_requested() - void wait(); // Returns when context is woken up. void yield(); // Allow other contexts to run before returning. - - // Return remaining time if notified; or <= 0 if not, and timeout thrown on throw overloads - microseconds wait(const microseconds &, const std::nothrow_t &); - template nothrow_overload wait(const duration &); - template throw_overload wait(const duration &); - - // Returns false if notified; true if time point reached, timeout thrown on throw_overloads - bool wait_until(const system_point &tp, const std::nothrow_t &); - template nothrow_overload wait_until(const system_point &tp); - template throw_overload wait_until(const system_point &tp); - - // Ignores notes. Throws if interrupted. - void sleep_until(const system_point &tp); - template void sleep(const duration &); - void sleep(const int &secs); }} namespace ircd::ctx @@ -52,83 +34,6 @@ namespace ircd namespace this_ctx = ctx::this_ctx; } -/// This overload matches ::sleep() and acts as a drop-in for ircd contexts. -/// interruption point. -inline void -ircd::ctx::this_ctx::sleep(const int &secs) -{ - sleep(seconds(secs)); -} - -/// Yield the context for a period of time and ignore notifications. sleep() -/// is like wait() but it only returns after the timeout and not because of a -/// note. -/// interruption point. -template -void -ircd::ctx::this_ctx::sleep(const duration &d) -{ - sleep_until(system_clock::now() + d); -} - -/// Wait for a notification until a point in time. If there is a notification -/// then context continues normally. If there's never a notification then an -/// exception (= timeout) is thrown. -/// interruption point. -template -ircd::throw_overload -ircd::ctx::this_ctx::wait_until(const system_point &tp) -{ - if(wait_until(tp)) - throw E{}; -} - -/// Wait for a notification until a point in time. If there is a notification -/// then returns true. If there's never a notification then returns false. -/// interruption point. this is not noexcept. -template -ircd::nothrow_overload -ircd::ctx::this_ctx::wait_until(const system_point &tp) -{ - return wait_until(tp, std::nothrow); -} - -/// Wait for a notification for at most some amount of time. If the duration is -/// reached without a notification then E (= timeout) is thrown. Otherwise, -/// returns the time remaining on the duration. -/// interruption point -template -ircd::throw_overload -ircd::ctx::this_ctx::wait(const duration &d) -{ - const auto ret - { - wait(d) - }; - - return ret <= duration(0)? - throw E{}: - ret; -} - -/// Wait for a notification for some amount of time. This function returns -/// when a context is notified. It always returns the duration remaining which -/// will be <= 0 to indicate a timeout without notification. -/// interruption point. this is not noexcept. -template -ircd::nothrow_overload -ircd::ctx::this_ctx::wait(const duration &d) -{ - const auto ret - { - wait(duration_cast(d), std::nothrow) - }; - - return duration_cast(ret); -} - /// View the name of the currently running context, or "*" if no context is /// currently running. inline ircd::string_view diff --git a/include/ircd/ctx/wait.h b/include/ircd/ctx/wait.h new file mode 100644 index 000000000..3cef557df --- /dev/null +++ b/include/ircd/ctx/wait.h @@ -0,0 +1,99 @@ +// The Construct +// +// Copyright (C) The Construct Developers, Authors & Contributors +// Copyright (C) 2016-2020 Jason Volk +// +// Permission to use, copy, modify, and/or distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice is present in all copies. The +// full license for this software is available in the LICENSE file. + +#pragma once +#define HAVE_IRCD_CTX_WAIT_H + +namespace ircd::ctx { inline namespace this_ctx +{ + // Returns when context is woken up. + void wait(); + + // Return remaining time if notified; or <= 0 if not, and timeout thrown on throw overloads + microseconds wait(const microseconds &, const std::nothrow_t &); + + template + nothrow_overload wait(const duration &); + + // timeout thrown if time point reached + template + throw_overload wait(const duration &); + + // Returns false if notified; true if time point reached + bool wait_until(const system_point &tp, const std::nothrow_t &); + + // Returns false if notified; true if time point reached + template + nothrow_overload wait_until(const system_point &tp); + + // timeout thrown if time point reached + template + throw_overload wait_until(const system_point &tp); +}} + +/// Wait for a notification until a point in time. If there is a notification +/// then context continues normally. If there's never a notification then an +/// exception (= timeout) is thrown. +/// interruption point. +template +ircd::throw_overload +ircd::ctx::this_ctx::wait_until(const system_point &tp) +{ + if(wait_until(tp)) + throw E{}; +} + +/// Wait for a notification until a point in time. If there is a notification +/// then returns true. If there's never a notification then returns false. +/// interruption point. this is not noexcept. +template +ircd::nothrow_overload +ircd::ctx::this_ctx::wait_until(const system_point &tp) +{ + return wait_until(tp, std::nothrow); +} + +/// Wait for a notification for at most some amount of time. If the duration is +/// reached without a notification then E (= timeout) is thrown. Otherwise, +/// returns the time remaining on the duration. +/// interruption point +template +ircd::throw_overload +ircd::ctx::this_ctx::wait(const duration &d) +{ + const auto ret + { + wait(d) + }; + + return ret <= duration(0)? + throw E{}: + ret; +} + +/// Wait for a notification for some amount of time. This function returns +/// when a context is notified. It always returns the duration remaining which +/// will be <= 0 to indicate a timeout without notification. +/// interruption point. this is not noexcept. +template +ircd::nothrow_overload +ircd::ctx::this_ctx::wait(const duration &d) +{ + const auto ret + { + wait(duration_cast(d), std::nothrow) + }; + + return duration_cast(ret); +}