libcopp  1.3.0
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 
13 #include <libcopp/utils/features.h>
17 
18 #ifdef LIBCOPP_MACRO_USE_SEGMENTED_STACKS
19 #define COROUTINE_CONTEXT_BASE_USING_BASE_SEGMENTED_STACKS(base_type) using base_type::caller_stack_;
20 #else
21 #define COROUTINE_CONTEXT_BASE_USING_BASE_SEGMENTED_STACKS(base_type)
22 #endif
23 
24 #define COROUTINE_CONTEXT_BASE_USING_BASE(base_type) \
25 protected: \
26  using base_type::caller_; \
27  using base_type::callee_; \
28  using base_type::callee_stack_; \
29  COROUTINE_CONTEXT_BASE_USING_BASE_SEGMENTED_STACKS(base_type)
30 
31 namespace copp {
32 
33  namespace details {
34  template <size_t N, bool BIGGER_THAN_16>
36 
37  template <size_t N>
39  static const size_t value = N;
40  };
41 
42  template <size_t N>
44  static const size_t value = 16;
45  };
46 
47  template <size_t N>
49  static const size_t value = align_helper_inner<N, N >= 16>::value;
50  };
51 
52  // We should align to at least 16 bytes, @see https://wiki.osdev.org/System_V_ABI for more details
53 #if (defined(__cplusplus) && __cplusplus >= 201103L) || (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L) || \
54  (defined(_MSC_VER) && _MSC_VER >= 1900)
55 #define COROUTINE_CONTEXT_BASE_ALIGN_UNIT_SIZE ::copp::details::align_helper<sizeof(max_align_t)>::value
56 #else
57 #define COROUTINE_CONTEXT_BASE_ALIGN_UNIT_SIZE ::copp::details::align_helper<2 * sizeof(long double)>::value
58 #endif
59 
61  } // namespace details
62 
67  public:
69  typedef std::function<int(void *)> callback_t;
70 
75  enum type {
76  EN_CRS_INVALID = 0,
81  };
82  };
83 
85  enum type {
86  EN_CFT_UNKNOWN = 0,
87  EN_CFT_FINISHED = 0x01,
88  EN_CFT_MASK = 0xFF,
89  };
90  };
91 
92  private:
94  int flags_;
95  callback_t runner_;
96  void * priv_data_;
98 
99  struct jump_src_data_t {
102  void * priv_data;
103  };
104 
106 
107  protected:
112 #ifdef LIBCOPP_MACRO_USE_SEGMENTED_STACKS
113  stack_context caller_stack_;
114 #endif
115 
116  private:
117 #if defined(LIBCOPP_DISABLE_ATOMIC_LOCK) && LIBCOPP_DISABLE_ATOMIC_LOCK
119 #else
121 #endif
122 
123  protected:
124  LIBCOPP_COPP_API coroutine_context() UTIL_CONFIG_NOEXCEPT;
125 
126  public:
128 
129  private:
130  coroutine_context(const coroutine_context &) UTIL_CONFIG_DELETED_FUNCTION;
131  coroutine_context &operator=(const coroutine_context &) UTIL_CONFIG_DELETED_FUNCTION;
132 
133 #if defined(UTIL_CONFIG_COMPILER_CXX_RVALUE_REFERENCES) && UTIL_CONFIG_COMPILER_CXX_RVALUE_REFERENCES
134  coroutine_context(const coroutine_context &&) UTIL_CONFIG_DELETED_FUNCTION;
135  coroutine_context &operator=(const coroutine_context &&) UTIL_CONFIG_DELETED_FUNCTION;
136 #endif
137 
138  public:
147  static LIBCOPP_COPP_API int create(coroutine_context *p, callback_t &runner, const stack_context &callee_stack,
148  size_t coroutine_size, size_t private_buffer_size) UTIL_CONFIG_NOEXCEPT;
149 
150  template <typename TRunner>
151  static LIBCOPP_COPP_API_HEAD_ONLY int create(coroutine_context *p, TRunner *runner, const stack_context &callee_stack,
152  size_t coroutine_size, size_t private_buffer_size) UTIL_CONFIG_NOEXCEPT {
153  return create(p, std::bind(&TRunner::operator(), runner, std::placeholders::_1), callee_stack, coroutine_size,
154  private_buffer_size);
155  }
156 
162  LIBCOPP_COPP_API int start(void *priv_data = UTIL_CONFIG_NULLPTR);
163 
169  LIBCOPP_COPP_API int resume(void *priv_data = UTIL_CONFIG_NULLPTR);
170 
171 
177  LIBCOPP_COPP_API int yield(void **priv_data = UTIL_CONFIG_NULLPTR);
178 
184  LIBCOPP_COPP_API bool set_flags(int flags);
185 
191  LIBCOPP_COPP_API bool unset_flags(int flags);
192 
198  LIBCOPP_COPP_API bool check_flags(int flags) const;
199 
200  protected:
204  UTIL_FORCEINLINE void run_and_recv_retcode(void *priv_data) {
205  if (!runner_) return;
206 
207  runner_ret_code_ = runner_(priv_data);
208  }
209 
210  public:
216 #if defined(UTIL_CONFIG_COMPILER_CXX_RVALUE_REFERENCES) && UTIL_CONFIG_COMPILER_CXX_RVALUE_REFERENCES
217  LIBCOPP_COPP_API int set_runner(callback_t &&runner);
218 #else
219  LIBCOPP_COPP_API int set_runner(const callback_t &runner);
220 #endif
221 
226  UTIL_FORCEINLINE const std::function<int(void *)> &get_runner() const UTIL_CONFIG_NOEXCEPT { return runner_; }
227 
232  UTIL_FORCEINLINE int get_ret_code() const UTIL_CONFIG_NOEXCEPT { return runner_ret_code_; }
233 
238  LIBCOPP_COPP_API bool is_finished() const UTIL_CONFIG_NOEXCEPT;
239 
243  UTIL_FORCEINLINE void *get_private_buffer() const UTIL_CONFIG_NOEXCEPT { return priv_data_; }
244 
248  UTIL_FORCEINLINE size_t get_private_buffer_size() const UTIL_CONFIG_NOEXCEPT { return private_buffer_size_; }
249 
250  public:
251  static UTIL_FORCEINLINE size_t align_private_data_size(size_t sz) {
252  // static size_t random_index = 0;
253  // UTIL_CONFIG_CONSTEXPR size_t random_mask = 63;
254  UTIL_CONFIG_CONSTEXPR size_t align_mask = COROUTINE_CONTEXT_BASE_ALIGN_UNIT_SIZE - 1;
255 
256  // align
257  sz += align_mask;
258  sz &= ~align_mask;
259 
260  // random
261  // ++random_index;
262  // random_index &= random_mask;
263  // sz += random_index * (align_mask + 1);
264  return sz;
265  }
266 
267  static inline size_t align_address_size(size_t sz) {
268  UTIL_CONFIG_CONSTEXPR size_t align_mask = COROUTINE_CONTEXT_BASE_ALIGN_UNIT_SIZE - 1;
269 
270  sz += align_mask;
271  sz &= ~align_mask;
272  return sz;
273  }
274  };
275 
276  namespace this_coroutine {
282  LIBCOPP_COPP_API coroutine_context *get_coroutine() UTIL_CONFIG_NOEXCEPT;
283 
290  template <typename Tc>
292  return static_cast<Tc *>(get_coroutine());
293  }
294 
300  LIBCOPP_COPP_API int yield(void **priv_data = UTIL_CONFIG_NULLPTR);
301  } // namespace this_coroutine
302 } // namespace copp
303 
304 #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
static LIBCOPP_COPP_API_HEAD_ONLY int create(coroutine_context *p, TRunner *runner, const stack_context &callee_stack, size_t coroutine_size, size_t private_buffer_size) UTIL_CONFIG_NOEXCEPT
#define LIBCOPP_COPP_API
#define LIBCOPP_COPP_API_HEAD_ONLY
status of safe coroutine context base
侵入式智能指针
UTIL_FORCEINLINE int get_ret_code() const UTIL_CONFIG_NOEXCEPT
get runner return code
UTIL_FORCEINLINE const std::function< int(void *)> & get_runner() const UTIL_CONFIG_NOEXCEPT
static UTIL_FORCEINLINE size_t align_private_data_size(size_t sz)
UTIL_FORCEINLINE void run_and_recv_retcode(void *priv_data)
coroutine entrance function
LIBCOPP_COPP_API int yield(void **priv_data=UTIL_CONFIG_NULLPTR)
yield current coroutine
#define COROUTINE_CONTEXT_BASE_ALIGN_UNIT_SIZE
UTIL_FORCEINLINE void * get_private_buffer() const UTIL_CONFIG_NOEXCEPT
get private buffer(raw pointer)
#define UTIL_FORCEINLINE
libcopp::util::lock::atomic_int_type< int > status_
static size_t align_address_size(size_t sz)
整数类型的原子操作跨平台适配 Licensed under the MIT licenses.
导入智能指针库 Licensed under the MIT licenses.
fcontext::fcontext_t callee_
LIBCOPP_COPP_API coroutine_context * get_coroutine() UTIL_CONFIG_NOEXCEPT
get current coroutine
struct LIBCOPP_COPP_API_HEAD_ONLY align_helper_inner
libcopp::util::intrusive_ptr< coroutine_context > ptr_t
base type of all coroutine context
UTIL_FORCEINLINE size_t get_private_buffer_size() const UTIL_CONFIG_NOEXCEPT
get private buffer size
导入高级库,hash、引用包装等 Licensed under the MIT licenses.
fcontext::fcontext_t caller_