libcopp  2.2.0
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 
11 #include <libcopp/fcontext/all.hpp>
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 
26 LIBCOPP_COPP_NAMESPACE_BEGIN
27 
28 namespace details {
29 template <size_t N1, size_t N2, bool BIGGER_THAN_16>
30 struct LIBCOPP_COPP_API_HEAD_ONLY align_helper_inner;
31 
32 template <size_t N1, size_t N2>
33 struct LIBCOPP_COPP_API_HEAD_ONLY align_helper_inner<N1, N2, true> {
34  static constexpr const size_t value = N1;
35 };
36 
37 template <size_t N1, size_t N2>
38 struct LIBCOPP_COPP_API_HEAD_ONLY align_helper_inner<N1, N2, false> {
39  static constexpr const size_t value = N2;
40 };
41 
42 template <size_t N, size_t COMPARE_TO>
43 struct 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 {
80  enum type {
81  EN_CRS_INVALID = 0,
86  };
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
101  using flag_t = flag_type;
102 
103  protected:
105  int flags_;
107  void *priv_data_;
109 
110 #if defined(LIBCOPP_DISABLE_ATOMIC_LOCK) && LIBCOPP_DISABLE_ATOMIC_LOCK
111  LIBCOPP_COPP_NAMESPACE_ID::util::lock::atomic_int_type<LIBCOPP_COPP_NAMESPACE_ID::util::lock::unsafe_int_type<int> >
112  status_;
113 #else
114  LIBCOPP_COPP_NAMESPACE_ID::util::lock::atomic_int_type<int> status_;
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:
130 
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:
160  UTIL_FORCEINLINE void run_and_recv_retcode(void *priv_data) {
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  UTIL_FORCEINLINE const std::function<int(void *)> &get_runner() const LIBCOPP_MACRO_NOEXCEPT { return runner_; }
179 
184  UTIL_FORCEINLINE int get_ret_code() const LIBCOPP_MACRO_NOEXCEPT { return runner_ret_code_; }
185 
190  LIBCOPP_COPP_API bool is_finished() const LIBCOPP_MACRO_NOEXCEPT;
191 
195  UTIL_FORCEINLINE void *get_private_buffer() const LIBCOPP_MACRO_NOEXCEPT { return priv_data_; }
196 
200  UTIL_FORCEINLINE size_t get_private_buffer_size() const LIBCOPP_MACRO_NOEXCEPT { return private_buffer_size_; }
201 
202  public:
203  UTIL_FORCEINLINE static size_t align_private_data_size(size_t sz) {
204  // static size_t random_index = 0;
205  // constexpr const size_t random_mask = 63;
206  constexpr const size_t align_mask = COROUTINE_CONTEXT_BASE_ALIGN_UNIT_SIZE - 1;
207 
208  // align
209  sz += align_mask;
210  sz &= ~align_mask;
211 
212  // random
213  // ++random_index;
214  // random_index &= random_mask;
215  // sz += random_index * (align_mask + 1);
216  return sz;
217  }
218 
219  static inline size_t align_address_size(size_t sz) {
220  constexpr const size_t align_mask = COROUTINE_CONTEXT_BASE_ALIGN_UNIT_SIZE - 1;
221 
222  sz += align_mask;
223  sz &= ~align_mask;
224  return sz;
225  }
226 
227  static inline size_t align_stack_size(size_t sz) {
228  constexpr const size_t align_mask = COROUTINE_CONTEXT_STACK_ALIGN_UNIT_SIZE - 1;
229 
230  sz += align_mask;
231  sz &= ~align_mask;
232  return sz;
233  }
234 
235 #if defined(LIBCOPP_MACRO_ENABLE_STD_EXCEPTION_PTR) && LIBCOPP_MACRO_ENABLE_STD_EXCEPTION_PTR
236  static inline void maybe_rethrow(std::exception_ptr &inout) {
237  COPP_UNLIKELY_IF (inout) {
238  std::exception_ptr eptr;
239  std::swap(eptr, inout);
240  std::rethrow_exception(eptr);
241  }
242  }
243 
244  UTIL_FORCEINLINE void maybe_rethrow() { maybe_rethrow(unhandle_exception_); }
245 #endif
246 
252  static LIBCOPP_COPP_API coroutine_context_base *get_this_coroutine_base() LIBCOPP_MACRO_NOEXCEPT;
253 
259  static LIBCOPP_COPP_API void set_this_coroutine_base(coroutine_context_base *ctx) LIBCOPP_MACRO_NOEXCEPT;
260 };
261 LIBCOPP_COPP_NAMESPACE_END
atomic wrapper fo integers Licensed under the MIT licenses.
base type of all coroutine context
UTIL_FORCEINLINE int get_ret_code() const LIBCOPP_MACRO_NOEXCEPT
get runner return code
UTIL_FORCEINLINE void * get_private_buffer() const LIBCOPP_MACRO_NOEXCEPT
get private buffer(raw pointer)
UTIL_FORCEINLINE void run_and_recv_retcode(void *priv_data)
coroutine entrance function
LIBCOPP_COPP_API bool set_flags(int flags) LIBCOPP_MACRO_NOEXCEPT
set all flags to true
UTIL_FORCEINLINE const std::function< int(void *)> & get_runner() const LIBCOPP_MACRO_NOEXCEPT
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
static UTIL_FORCEINLINE size_t align_private_data_size(size_t sz)
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
static size_t align_stack_size(size_t sz)
LIBCOPP_COPP_API bool check_flags(int flags) const LIBCOPP_MACRO_NOEXCEPT
check flags
UTIL_FORCEINLINE size_t get_private_buffer_size() const LIBCOPP_MACRO_NOEXCEPT
get private buffer size
LIBCOPP_COPP_API coroutine_context_base() LIBCOPP_MACRO_NOEXCEPT
LIBCOPP_COPP_NAMESPACE_ID::util::lock::atomic_int_type< int > status_
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 UTIL_FORCEINLINE
#define COROUTINE_CONTEXT_BASE_ALIGN_UNIT_SIZE
#define COROUTINE_CONTEXT_STACK_ALIGN_UNIT_SIZE
#define COPP_UNLIKELY_IF(...)
Definition: features.h:117
struct LIBCOPP_COPP_API_HEAD_ONLY align_helper_inner
void swap(intrusive_ptr< T > &lhs, intrusive_ptr< T > &rhs)
status of safe coroutine context base