libcopp  1.2.1
coroutine_context.h
Go to the documentation of this file.
1 #ifndef COPP_COROUTINE_CONTEXT_COROUTINE_CONTEXT_BASE_H
2 #define COPP_COROUTINE_CONTEXT_COROUTINE_CONTEXT_BASE_H
3 
4 #pragma once
5 
6 #include <cstddef>
7 
11 #include <libcopp/utils/features.h>
15 
16 #ifdef LIBCOPP_MACRO_USE_SEGMENTED_STACKS
17 #define COROUTINE_CONTEXT_BASE_USING_BASE_SEGMENTED_STACKS(base_type) using base_type::caller_stack_;
18 #else
19 #define COROUTINE_CONTEXT_BASE_USING_BASE_SEGMENTED_STACKS(base_type)
20 #endif
21 
22 #define COROUTINE_CONTEXT_BASE_USING_BASE(base_type) \
23 protected: \
24  using base_type::caller_; \
25  using base_type::callee_; \
26  using base_type::callee_stack_; \
27  COROUTINE_CONTEXT_BASE_USING_BASE_SEGMENTED_STACKS(base_type)
28 
29 namespace copp {
30 
31  namespace details {
32  template <size_t N, bool BIGGER_THAN_16>
34 
35  template <size_t N>
36  struct align_helper_inner<N, true> {
37  static const size_t value = N;
38  };
39 
40  template <size_t N>
41  struct align_helper_inner<N, false> {
42  static const size_t value = 16;
43  };
44 
45  template <size_t N>
46  struct align_helper {
47  static const size_t value = align_helper_inner<N, N >= 16>::value;
48  };
49 
50  // We should align to at least 16 bytes, @see https://wiki.osdev.org/System_V_ABI for more details
51 #if (defined(__cplusplus) && __cplusplus >= 201103L) || (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L) || \
52  (defined(_MSC_VER) && _MSC_VER >= 1900)
53 #define COROUTINE_CONTEXT_BASE_ALIGN_UNIT_SIZE ::copp::details::align_helper<sizeof(max_align_t)>::value
54 #else
55 #define COROUTINE_CONTEXT_BASE_ALIGN_UNIT_SIZE ::copp::details::align_helper<2 * sizeof(long double)>::value
56 #endif
57 
59  } // namespace details
60 
65  public:
67  typedef std::function<int(void *)> callback_t;
68 
72  struct status_t {
73  enum type {
74  EN_CRS_INVALID = 0,
79  };
80  };
81 
82  struct flag_t {
83  enum type {
84  EN_CFT_UNKNOWN = 0,
85  EN_CFT_FINISHED = 0x01,
86  EN_CFT_MASK = 0xFF,
87  };
88  };
89 
90  private:
92  int flags_;
93  callback_t runner_;
94  void * priv_data_;
96 
97  struct jump_src_data_t {
100  void * priv_data;
101  };
102 
104 
105  protected:
110 #ifdef LIBCOPP_MACRO_USE_SEGMENTED_STACKS
111  stack_context caller_stack_;
112 #endif
113 
114  private:
115 #if defined(LIBCOPP_DISABLE_ATOMIC_LOCK) && LIBCOPP_DISABLE_ATOMIC_LOCK
117 #else
119 #endif
120 
121  protected:
122  coroutine_context() UTIL_CONFIG_NOEXCEPT;
123 
124  public:
126 
127  public:
136  static int create(coroutine_context *p, callback_t &runner, const stack_context &callee_stack, size_t coroutine_size,
137  size_t private_buffer_size) UTIL_CONFIG_NOEXCEPT;
138 
139  template <typename TRunner>
140  static int create(coroutine_context *p, TRunner *runner, const stack_context &callee_stack, size_t coroutine_size,
141  size_t private_buffer_size) UTIL_CONFIG_NOEXCEPT {
142  return create(p, std::bind(&TRunner::operator(), runner, std::placeholders::_1), callee_stack, coroutine_size,
143  private_buffer_size);
144  }
145 
151  int start(void *priv_data = UTIL_CONFIG_NULLPTR);
152 
158  int resume(void *priv_data = UTIL_CONFIG_NULLPTR);
159 
160 
166  int yield(void **priv_data = UTIL_CONFIG_NULLPTR);
167 
173  bool set_flags(int flags);
174 
180  bool unset_flags(int flags);
181 
187  bool check_flags(int flags) const;
188 
189  protected:
193  inline void run_and_recv_retcode(void *priv_data) {
194  if (!runner_) return;
195 
196  runner_ret_code_ = runner_(priv_data);
197  }
198 
199  public:
205 #if defined(UTIL_CONFIG_COMPILER_CXX_RVALUE_REFERENCES) && UTIL_CONFIG_COMPILER_CXX_RVALUE_REFERENCES
206  int set_runner(callback_t &&runner);
207 #else
208  int set_runner(const callback_t &runner);
209 #endif
210 
215  inline const std::function<int(void *)> &get_runner() const UTIL_CONFIG_NOEXCEPT { return runner_; }
216 
221  inline int get_ret_code() const UTIL_CONFIG_NOEXCEPT { return runner_ret_code_; }
222 
227  bool is_finished() const UTIL_CONFIG_NOEXCEPT;
228 
232  inline void *get_private_buffer() const UTIL_CONFIG_NOEXCEPT { return priv_data_; }
233 
237  inline size_t get_private_buffer_size() const UTIL_CONFIG_NOEXCEPT { return private_buffer_size_; }
238 
239  public:
240  static inline size_t align_private_data_size(size_t sz) {
241  // static size_t random_index = 0;
242  // UTIL_CONFIG_CONSTEXPR size_t random_mask = 63;
243  UTIL_CONFIG_CONSTEXPR size_t align_mask = COROUTINE_CONTEXT_BASE_ALIGN_UNIT_SIZE - 1;
244 
245  // align
246  sz += align_mask;
247  sz &= ~align_mask;
248 
249  // random
250  // ++random_index;
251  // random_index &= random_mask;
252  // sz += random_index * (align_mask + 1);
253  return sz;
254  }
255 
256  static inline size_t align_address_size(size_t sz) {
257  UTIL_CONFIG_CONSTEXPR size_t align_mask = COROUTINE_CONTEXT_BASE_ALIGN_UNIT_SIZE - 1;
258 
259  sz += align_mask;
260  sz &= ~align_mask;
261  return sz;
262  }
263  };
264 
265  namespace this_coroutine {
271  coroutine_context *get_coroutine() UTIL_CONFIG_NOEXCEPT;
272 
279  template <typename Tc>
280  Tc *get() {
281  return static_cast<Tc *>(get_coroutine());
282  }
283 
289  int yield(void **priv_data = UTIL_CONFIG_NULLPTR);
290  } // namespace this_coroutine
291 } // namespace copp
292 
293 #endif
UTIL_CONFIG_STATIC_ASSERT(COROUTINE_CONTEXT_BASE_ALIGN_UNIT_SIZE >=16 &&0==COROUTINE_CONTEXT_BASE_ALIGN_UNIT_SIZE% 16)
std::function< int(void *)> callback_t
status of safe coroutine context base
const std::function< int(void *)> & get_runner() const UTIL_CONFIG_NOEXCEPT
#define COROUTINE_CONTEXT_BASE_ALIGN_UNIT_SIZE
void run_and_recv_retcode(void *priv_data)
coroutine entrance function
coroutine_context * get_coroutine() UTIL_CONFIG_NOEXCEPT
get current coroutine
static size_t align_address_size(size_t sz)
util::lock::atomic_int_type< int > status_
int get_ret_code() const UTIL_CONFIG_NOEXCEPT
get runner return code
int yield(void **priv_data=UTIL_CONFIG_NULLPTR)
yield current coroutine
整数类型的原子操作跨平台适配 Licensed under the MIT licenses.
导入智能指针库 Licensed under the MIT licenses.
size_t get_private_buffer_size() const UTIL_CONFIG_NOEXCEPT
get private buffer size
fcontext::fcontext_t callee_
void * get_private_buffer() const UTIL_CONFIG_NOEXCEPT
get private buffer(raw pointer)
std::intrusive_ptr< coroutine_context > ptr_t
base type of all coroutine context
导入高级库,hash、引用包装等 Licensed under the MIT licenses.
fcontext::fcontext_t caller_
static size_t align_private_data_size(size_t sz)