libcopp 2.3.1
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
coroutine_context_base.h
Go to the documentation of this file.
1// Copyright 2023 owent
2
3#pragma once
4
5#include <libcopp/utils/config/libcopp_build_features.h>
6
12
13// clang-format off
14#include <libcopp/utils/config/stl_include_prefix.h> // NOLINT(build/include_order)
15// clang-format on
16#include <cstddef>
17#include <functional>
18#include <memory>
19#if defined(LIBCOPP_MACRO_ENABLE_STD_EXCEPTION_PTR) && LIBCOPP_MACRO_ENABLE_STD_EXCEPTION_PTR
20# include <exception>
21#endif
22// clang-format off
23#include <libcopp/utils/config/stl_include_suffix.h> // NOLINT(build/include_order)
24// clang-format on
25
26LIBCOPP_COPP_NAMESPACE_BEGIN
27
28namespace details {
29template <size_t N1, size_t N2, bool BIGGER_THAN_16>
30struct LIBCOPP_COPP_API_HEAD_ONLY align_helper_inner;
31
32template <size_t N1, size_t N2>
33struct LIBCOPP_COPP_API_HEAD_ONLY align_helper_inner<N1, N2, true> {
34 static constexpr const size_t value = N1;
35};
36
37template <size_t N1, size_t N2>
38struct LIBCOPP_COPP_API_HEAD_ONLY align_helper_inner<N1, N2, false> {
39 static constexpr const size_t value = N2;
40};
41
42template <size_t N, size_t COMPARE_TO>
43struct LIBCOPP_COPP_API_HEAD_ONLY align_helper {
44 static constexpr const size_t value = align_helper_inner<N, COMPARE_TO, N >= COMPARE_TO>::value;
45};
46
47// We should align to at least 16 bytes, @see https://wiki.osdev.org/System_V_ABI for more details
48#if (defined(__cplusplus) && __cplusplus >= 201103L) || (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L) || \
49 (defined(_MSC_VER) && _MSC_VER >= 1900)
50# define COROUTINE_CONTEXT_BASE_ALIGN_UNIT_SIZE \
51 LIBCOPP_COPP_NAMESPACE_ID::details::align_helper<sizeof(max_align_t), 16>::value
52#else
53# define COROUTINE_CONTEXT_BASE_ALIGN_UNIT_SIZE \
54 LIBCOPP_COPP_NAMESPACE_ID::details::align_helper<2 * sizeof(size_t), 16>::value
55#endif
56
57// Some architecture may require stack to be aligned to 64
58// @see "3.2.2 The Stack Frame" of https://github.com/hjl-tools/x86-psABI/wiki/x86-64-psABI-1.0.pdf
59// More documents about x86/x86_64 canbe found at https://stackoverflow.com/tags/x86/info
60#define COROUTINE_CONTEXT_STACK_ALIGN_UNIT_SIZE \
61 LIBCOPP_COPP_NAMESPACE_ID::details::align_helper<COROUTINE_CONTEXT_BASE_ALIGN_UNIT_SIZE, 64>::value
62
64 "COROUTINE_CONTEXT_BASE_ALIGN_UNIT_SIZE");
66 "COROUTINE_CONTEXT_STACK_ALIGN_UNIT_SIZE");
67} // namespace details
68
73 public:
74 using callback_type = std::function<int(void *)>;
75
79 struct LIBCOPP_COPP_API status_type {
87 };
88
89 struct LIBCOPP_COPP_API flag_type {
90 enum type {
91 EN_CFT_UNKNOWN = 0,
92 EN_CFT_FINISHED = 0x01,
93 EN_CFT_IS_FIBER = 0x02,
94 EN_CFT_MASK = 0xFF,
95 };
96 };
97
98 // Compability with libcopp-1.x
102
103 protected:
105 int flags_;
109
110#if LIBCOPP_MACRO_ENABLE_MULTI_THREAD
111 LIBCOPP_COPP_NAMESPACE_ID::util::lock::atomic_int_type<int> status_;
112#else
113 LIBCOPP_COPP_NAMESPACE_ID::util::lock::atomic_int_type<LIBCOPP_COPP_NAMESPACE_ID::util::lock::unsafe_int_type<int> >
115#endif
116
117#if defined(LIBCOPP_MACRO_ENABLE_STD_EXCEPTION_PTR) && LIBCOPP_MACRO_ENABLE_STD_EXCEPTION_PTR
118 std::exception_ptr unhandle_exception_;
119#endif
120
121 protected:
122 LIBCOPP_COPP_API coroutine_context_base() LIBCOPP_MACRO_NOEXCEPT;
123
124 public:
125 LIBCOPP_COPP_API ~coroutine_context_base();
126
127 private:
129 coroutine_context_base &operator=(const coroutine_context_base &) = delete;
130
132 coroutine_context_base &operator=(const coroutine_context_base &&) = delete;
133
134 public:
140 LIBCOPP_COPP_API bool set_flags(int flags) LIBCOPP_MACRO_NOEXCEPT;
141
147 LIBCOPP_COPP_API bool unset_flags(int flags) LIBCOPP_MACRO_NOEXCEPT;
148
154 LIBCOPP_COPP_API bool check_flags(int flags) const LIBCOPP_MACRO_NOEXCEPT;
155
156 protected:
161 if (!runner_) return;
162
163 runner_ret_code_ = runner_(priv_data);
164 }
165
166 public:
172 LIBCOPP_COPP_API int set_runner(callback_type &&runner);
173
178 LIBCOPP_UTIL_FORCEINLINE const std::function<int(void *)> &get_runner() const LIBCOPP_MACRO_NOEXCEPT {
179 return runner_;
180 }
181
186 LIBCOPP_UTIL_FORCEINLINE int get_ret_code() const LIBCOPP_MACRO_NOEXCEPT { return runner_ret_code_; }
187
192 LIBCOPP_COPP_API bool is_finished() const LIBCOPP_MACRO_NOEXCEPT;
193
197 LIBCOPP_UTIL_FORCEINLINE void *get_private_buffer() const LIBCOPP_MACRO_NOEXCEPT { return priv_data_; }
198
202 LIBCOPP_UTIL_FORCEINLINE size_t get_private_buffer_size() const LIBCOPP_MACRO_NOEXCEPT {
204 }
205
206 public:
208 // static size_t random_index = 0;
209 // constexpr const size_t random_mask = 63;
210 constexpr const size_t align_mask = COROUTINE_CONTEXT_BASE_ALIGN_UNIT_SIZE - 1;
211
212 // align
213 sz += align_mask;
214 sz &= ~align_mask;
215
216 // random
217 // ++random_index;
218 // random_index &= random_mask;
219 // sz += random_index * (align_mask + 1);
220 return sz;
221 }
222
223 static inline size_t align_address_size(size_t sz) {
224 constexpr const size_t align_mask = COROUTINE_CONTEXT_BASE_ALIGN_UNIT_SIZE - 1;
225
226 sz += align_mask;
227 sz &= ~align_mask;
228 return sz;
229 }
230
231 static inline size_t align_stack_size(size_t sz) {
232 constexpr const size_t align_mask = COROUTINE_CONTEXT_STACK_ALIGN_UNIT_SIZE - 1;
233
234 sz += align_mask;
235 sz &= ~align_mask;
236 return sz;
237 }
238
239#if defined(LIBCOPP_MACRO_ENABLE_STD_EXCEPTION_PTR) && LIBCOPP_MACRO_ENABLE_STD_EXCEPTION_PTR
240 static inline void maybe_rethrow(std::exception_ptr &inout) {
242 std::exception_ptr eptr;
243 std::swap(eptr, inout);
244 std::rethrow_exception(eptr);
245 }
246 }
247
248 LIBCOPP_UTIL_FORCEINLINE void maybe_rethrow() { maybe_rethrow(unhandle_exception_); }
249#endif
250
256 static LIBCOPP_COPP_API coroutine_context_base *get_this_coroutine_base() LIBCOPP_MACRO_NOEXCEPT;
257
263 static LIBCOPP_COPP_API void set_this_coroutine_base(coroutine_context_base *ctx) LIBCOPP_MACRO_NOEXCEPT;
264};
265LIBCOPP_COPP_NAMESPACE_END
atomic wrapper fo integers Licensed under the MIT licenses.
base type of all coroutine context
LIBCOPP_UTIL_FORCEINLINE const std::function< int(void *)> & get_runner() const LIBCOPP_MACRO_NOEXCEPT
LIBCOPP_COPP_API bool set_flags(int flags) LIBCOPP_MACRO_NOEXCEPT
set all flags to true
LIBCOPP_COPP_API int set_runner(callback_type &&runner)
set runner
static LIBCOPP_COPP_API void set_this_coroutine_base(coroutine_context_base *ctx) LIBCOPP_MACRO_NOEXCEPT
set current coroutine
LIBCOPP_COPP_NAMESPACE_ID::util::lock::atomic_int_type< LIBCOPP_COPP_NAMESPACE_ID::util::lock::unsafe_int_type< int > > status_
static size_t align_address_size(size_t sz)
static LIBCOPP_COPP_API coroutine_context_base * get_this_coroutine_base() LIBCOPP_MACRO_NOEXCEPT
get current coroutine
LIBCOPP_UTIL_FORCEINLINE void * get_private_buffer() const LIBCOPP_MACRO_NOEXCEPT
get private buffer(raw pointer)
static size_t align_stack_size(size_t sz)
LIBCOPP_COPP_API bool check_flags(int flags) const LIBCOPP_MACRO_NOEXCEPT
check flags
LIBCOPP_UTIL_FORCEINLINE int get_ret_code() const LIBCOPP_MACRO_NOEXCEPT
get runner return code
LIBCOPP_COPP_API coroutine_context_base() LIBCOPP_MACRO_NOEXCEPT
static LIBCOPP_UTIL_FORCEINLINE size_t align_private_data_size(size_t sz)
LIBCOPP_UTIL_FORCEINLINE void run_and_recv_retcode(void *priv_data)
coroutine entrance function
LIBCOPP_UTIL_FORCEINLINE size_t get_private_buffer_size() const LIBCOPP_MACRO_NOEXCEPT
get private buffer size
LIBCOPP_COPP_API bool is_finished() const LIBCOPP_MACRO_NOEXCEPT
get runner return code
LIBCOPP_COPP_API bool unset_flags(int flags) LIBCOPP_MACRO_NOEXCEPT
set all flags to false
std::function< int(void *)> callback_type
#define LIBCOPP_UTIL_FORCEINLINE
#define LIBCOPP_UTIL_UNLIKELY_CONDITION(__C)
#define COROUTINE_CONTEXT_BASE_ALIGN_UNIT_SIZE
#define COROUTINE_CONTEXT_STACK_ALIGN_UNIT_SIZE
struct LIBCOPP_COPP_API_HEAD_ONLY align_helper_inner
LIBCOPP_COPP_API_HEAD_ONLY void swap(LIBCOPP_COPP_NAMESPACE_ID::memory::strong_rc_ptr< T > &a, LIBCOPP_COPP_NAMESPACE_ID::memory::strong_rc_ptr< T > &b) noexcept
Support std::swap for strong_rc_ptr.
Definition rc_ptr.h:1377
status of safe coroutine context base