From e97e70b42765e0798b9a5d3e069b760d1d220a45 Mon Sep 17 00:00:00 2001 From: q66 Date: Tue, 7 Mar 2017 17:33:56 +0100 Subject: [PATCH] constructor cleanup, const correctness, swap fixes, explicit bool, comments --- ostd/coroutine.hh | 113 +++++++++++++++++----------------------------- ostd/platform.hh | 6 +++ 2 files changed, 48 insertions(+), 71 deletions(-) diff --git a/ostd/coroutine.hh b/ostd/coroutine.hh index 36625e7..d88f8fe 100644 --- a/ostd/coroutine.hh +++ b/ostd/coroutine.hh @@ -20,21 +20,6 @@ #include "ostd/platform.hh" #include "ostd/range.hh" -/* from boost.context */ -#ifdef OSTD_PLATFORM_WIN32 -# if (defined(i386) || defined(__i386__) || defined(__i386) || \ - defined(__i486__) || defined(__i586__) || defined(__i686__) || \ - defined(__X86__) || defined(_X86_) || defined(__THW_INTEL__) || \ - defined(__I86__) || defined(__INTEL__) || defined(__IA32__) || \ - defined(_M_IX86) || defined(_I86_)) -# define OSTD_CONTEXT_CDECL __cdecl -# endif -#endif - -#ifndef OSTD_CONTEXT_CDECL -#define OSTD_CONTEXT_CDECL -#endif - namespace ostd { constexpr size_t COROUTINE_DEFAULT_STACK_SIZE = SIGSTKSZ; @@ -59,27 +44,27 @@ namespace detail { }; extern "C" OSTD_EXPORT - transfer_t OSTD_CONTEXT_CDECL ostd_jump_fcontext( + transfer_t OSTD_CDECL ostd_jump_fcontext( fcontext_t const to, void *vp ); extern "C" OSTD_EXPORT - fcontext_t OSTD_CONTEXT_CDECL ostd_make_fcontext( + fcontext_t OSTD_CDECL ostd_make_fcontext( void *sp, size_t size, void (*fn)(transfer_t) ); extern "C" OSTD_EXPORT - transfer_t OSTD_CONTEXT_CDECL ostd_ontop_fcontext( + transfer_t OSTD_CDECL ostd_ontop_fcontext( fcontext_t const to, void *vp, transfer_t (*fn)(transfer_t) ); - struct forced_unwind { - fcontext_t ctx; - forced_unwind(fcontext_t c): ctx(c) {} - }; - struct coroutine_context { protected: + struct forced_unwind { + fcontext_t ctx; + forced_unwind(fcontext_t c): ctx(c) {} + }; + coroutine_context() {} coroutine_context(coroutine_context const &) = delete; @@ -121,10 +106,11 @@ namespace detail { } void swap(coroutine_context &other) noexcept { - std::swap(p_stack, other.p_stack); - std::swap(p_coro, other.p_coro); - std::swap(p_orig, other.p_orig); - std::swap(p_except, other.p_except); + using std::swap; + swap(p_stack, other.p_stack); + swap(p_coro, other.p_coro); + swap(p_orig, other.p_orig); + swap(p_except, other.p_except); } void make_context(size_t ss, void (*callp)(transfer_t)) { @@ -153,7 +139,8 @@ namespace detail { } void swap(arg_wrapper &other) { - std::swap(p_arg, other.p_arg); + using std::swap; + swap(p_arg, other.p_arg); } private: @@ -173,7 +160,8 @@ namespace detail { } void swap(arg_wrapper &other) { - std::swap(p_arg, other.p_arg); + using std::swap; + swap(p_arg, other.p_arg); } private: @@ -193,7 +181,8 @@ namespace detail { } void swap(arg_wrapper &other) { - std::swap(p_arg, other.p_arg); + using std::swap; + swap(p_arg, other.p_arg); } private: @@ -240,14 +229,6 @@ namespace detail { template struct coro_base: coroutine_context { protected: - coro_base() {} - - coro_base(coro_base const &) = delete; - coro_base(coro_base &&c) = default; - - coro_base &operator=(coro_base const &) = delete; - coro_base &operator=(coro_base &&c) = default; - struct yielder { yielder(coro_base &coro): p_coro(coro) {} @@ -276,8 +257,9 @@ namespace detail { } void swap(coro_base &other) { - std::swap(p_args, other.p_args); - std::swap(p_result, other.p_result); + using std::swap; + swap(p_args, other.p_args); + swap(p_result, other.p_result); coroutine_context::swap(other); } @@ -291,14 +273,6 @@ namespace detail { coroutine_range iter(); protected: - coro_base() {} - - coro_base(coro_base const &) = delete; - coro_base(coro_base &&c) = default; - - coro_base &operator=(coro_base const &) = delete; - coro_base &operator=(coro_base &&c) = default; - struct yielder { yielder(coro_base &coro): p_coro(coro) {} @@ -321,7 +295,8 @@ namespace detail { } void swap(coro_base &other) { - std::swap(p_result, other.p_result); + using std::swap; + swap(p_result, other.p_result); coroutine_context::swap(other); } @@ -332,14 +307,6 @@ namespace detail { template struct coro_base: coroutine_context { protected: - coro_base() {} - - coro_base(coro_base const &) = delete; - coro_base(coro_base &&c) = default; - - coro_base &operator=(coro_base const &) = delete; - coro_base &operator=(coro_base &&c) = default; - struct yielder { yielder(coro_base &coro): p_coro(coro) {} @@ -364,7 +331,8 @@ namespace detail { } void swap(coro_base &other) { - std::swap(p_args, other.p_args); + using std::swap; + swap(p_args, other.p_args); coroutine_context::swap(other); } @@ -375,14 +343,6 @@ namespace detail { template<> struct coro_base: coroutine_context { protected: - coro_base() {} - - coro_base(coro_base const &) = delete; - coro_base(coro_base &&c) = default; - - coro_base &operator=(coro_base const &) = delete; - coro_base &operator=(coro_base &&c) = default; - struct yielder { yielder(coro_base &coro): p_coro(coro) {} @@ -416,10 +376,14 @@ private: public: using yield_type = typename detail::coro_base::yielder; + /* we have no way to assign a function anyway... */ + coroutine() = delete; + template coroutine(F func, size_t ss = COROUTINE_DEFAULT_STACK_SIZE): - p_func(std::move(func)) + base_t(), p_func(std::move(func)) { + /* that way there is no context creation/stack allocation */ if (!p_func) { return; } @@ -441,14 +405,14 @@ public: } ~coroutine() { - /* we have to check both because of potential moves */ if (!p_func) { + /* the stack has already unwound by a normal return */ return; } this->unwind(); } - operator bool() const { + explicit operator bool() const { return bool(p_func); } @@ -469,17 +433,24 @@ public: } private: + /* the main entry point of the coroutine */ static void context_call(detail::transfer_t t) { auto &self = *(static_cast(t.data)); self.p_orig = t.ctx; try { self.call_helper(self.p_func, std::index_sequence_for{}); - } catch (detail::forced_unwind v) { + } catch (detail::coroutine_context::forced_unwind v) { + /* forced_unwind is unique */ self.p_orig = v.ctx; } catch (...) { + /* some other exception, will be rethrown later */ self.p_except = std::current_exception(); } + /* the func has fully finished here, so mark dead, stack + * will be freed by the coroutine's destructor later + */ self.p_func = nullptr; + /* perform a last switch back to original context */ self.yield_jump(); } @@ -522,7 +493,7 @@ struct coroutine_range: input_range> { return p_item.value(); } - bool equals_front(coroutine_range const &g) { + bool equals_front(coroutine_range const &g) const { return p_coro == g.p_coro; } private: diff --git a/ostd/platform.hh b/ostd/platform.hh index cfc19d3..65c7343 100644 --- a/ostd/platform.hh +++ b/ostd/platform.hh @@ -99,6 +99,12 @@ # endif #endif +#if defined(OSTD_PLATFORM_WIN32) && !defined(OSTD_PLATFORM_WIN64) +# define OSTD_CDECL __cdecl +#else +# define OSTD_CDECL +#endif + namespace ostd { #if defined(OSTD_TOOLCHAIN_GNU)