3 #include <libcopp/utils/config/libcopp_build_features.h>
13 #if defined(COPP_MACRO_THREAD_LOCAL)
26 #ifdef LIBCOPP_MACRO_USE_SEGMENTED_STACKS
28 void __splitstack_getcontext(
void *[COPP_MACRO_SEGMENTED_STACK_NUMBER]);
30 void __splitstack_setcontext(
void *[COPP_MACRO_SEGMENTED_STACK_NUMBER]);
32 void __splitstack_releasecontext(
void *[COPP_MACRO_SEGMENTED_STACK_NUMBER]);
34 void __splitstack_block_signals_context(
void *[COPP_MACRO_SEGMENTED_STACK_NUMBER],
int *,
int *);
38 LIBCOPP_COPP_NAMESPACE_BEGIN
41 #if defined(LIBCOPP_LOCK_DISABLE_THIS_MT) && LIBCOPP_LOCK_DISABLE_THIS_MT
43 #elif defined(COPP_MACRO_THREAD_LOCAL)
52 #if (defined(LIBCOPP_LOCK_DISABLE_THIS_MT) && LIBCOPP_LOCK_DISABLE_THIS_MT) || defined(COPP_MACRO_THREAD_LOCAL)
53 gt_current_coroutine = p;
61 #if (defined(LIBCOPP_LOCK_DISABLE_THIS_MT) && LIBCOPP_LOCK_DISABLE_THIS_MT) || defined(COPP_MACRO_THREAD_LOCAL)
62 return gt_current_coroutine;
71 : runner_ret_code_(0),
75 private_buffer_size_(0),
81 if (flags & flag_type::EN_CFT_MASK) {
90 if (flags & flag_type::EN_CFT_MASK) {
99 return 0 != (flags_ & flags);
128 LIBCOPP_MACRO_NOEXCEPT {
136 if (
nullptr != src) {
142 if (
nullptr != src) {
147 #ifdef LIBCOPP_MACRO_USE_SEGMENTED_STACKS
151 if (
nullptr != jump_transfer.
from_co) {
155 sizeof(from_sctx.segments_ctx));
158 __splitstack_getcontext(from_sctx.segments_ctx);
160 __splitstack_setcontext(to_sctx.segments_ctx);
165 assert(src_ctx.data);
166 if (
nullptr == src_ctx.data) {
177 if (
nullptr == ins_ptr) {
183 ins_ptr->
caller_ = src_ctx.fctx;
186 if (
nullptr != jump_src.
from_co) {
194 #if defined(LIBCOPP_MACRO_ENABLE_STD_EXCEPTION_PTR) && LIBCOPP_MACRO_ENABLE_STD_EXCEPTION_PTR
198 #if defined(LIBCOPP_MACRO_ENABLE_STD_EXCEPTION_PTR) && LIBCOPP_MACRO_ENABLE_STD_EXCEPTION_PTR
200 ins_ptr->unhandle_exception_ = std::current_exception();
222 LIBCOPP_COPP_NAMESPACE_ID::fcontext::transfer_t res;
229 #ifdef LIBCOPP_MACRO_USE_SEGMENTED_STACKS
230 assert(&from_sctx != &to_sctx);
235 libcopp_internal_api_set::splitstack_swapcontext(from_sctx, to_sctx, jump_transfer);
238 if (
nullptr == res.data) {
275 #ifdef LIBCOPP_MACRO_USE_SEGMENTED_STACKS
286 size_t private_buffer_size) LIBCOPP_MACRO_NOEXCEPT {
292 if (0 != (private_buffer_size & (
sizeof(
size_t) - 1))) {
296 if (0 != (coroutine_size & (
sizeof(
size_t) - 1))) {
300 size_t stack_offset = align_stack_size(private_buffer_size + coroutine_size);
301 if (
nullptr == callee_stack.sp || callee_stack.size <= stack_offset) {
312 size_t this_offset =
reinterpret_cast<unsigned char *
>(callee_stack.sp) -
reinterpret_cast<unsigned char *
>(p);
313 if (this_offset <
sizeof(
coroutine_context) + private_buffer_size || this_offset > stack_offset) {
318 p->set_runner(std::move(runner));
320 if (&p->callee_stack_ != &callee_stack) {
321 p->callee_stack_ = callee_stack;
323 p->private_buffer_size_ = private_buffer_size;
326 p->priv_data_ =
reinterpret_cast<unsigned char *
>(p->callee_stack_.sp) - p->private_buffer_size_;
328 p->callee_stack_.size - stack_offset,
330 if (
nullptr == p->callee_) {
337 #if defined(LIBCOPP_MACRO_ENABLE_STD_EXCEPTION_PTR) && LIBCOPP_MACRO_ENABLE_STD_EXCEPTION_PTR
339 std::exception_ptr eptr;
340 int ret =
start(eptr, priv_data);
345 LIBCOPP_COPP_API
int coroutine_context::start(std::exception_ptr &unhandled,
void *priv_data) LIBCOPP_MACRO_NOEXCEPT {
353 #if defined(LIBCOPP_MACRO_ENABLE_WIN_FIBER) && LIBCOPP_MACRO_ENABLE_WIN_FIBER
386 #if defined(LIBCOPP_MACRO_ENABLE_WIN_FIBER) && LIBCOPP_MACRO_ENABLE_WIN_FIBER
391 jump_data.
to_co =
this;
394 #ifdef LIBCOPP_MACRO_USE_SEGMENTED_STACKS
406 #if defined(LIBCOPP_MACRO_ENABLE_STD_EXCEPTION_PTR) && LIBCOPP_MACRO_ENABLE_STD_EXCEPTION_PTR
408 std::swap(unhandled, unhandle_exception_);
416 #if defined(LIBCOPP_MACRO_ENABLE_STD_EXCEPTION_PTR) && LIBCOPP_MACRO_ENABLE_STD_EXCEPTION_PTR
418 return start(unhandled, priv_data);
423 if (
nullptr == callee_) {
427 int from_status = status_type::EN_CRS_RUNNING;
428 int to_status = status_type::EN_CRS_READY;
429 if (check_flags(flag_type::EN_CFT_FINISHED)) {
430 to_status = status_type::EN_CRS_FINISHED;
432 if (
false == status_.compare_exchange_strong(from_status, to_status,
435 switch (from_status) {
436 case status_type::EN_CRS_INVALID:
438 case status_type::EN_CRS_READY:
440 case status_type::EN_CRS_FINISHED:
441 case status_type::EN_CRS_EXITED:
451 jump_data.
to_co =
nullptr;
453 #ifdef LIBCOPP_MACRO_USE_SEGMENTED_STACKS
454 jump_to(caller_, callee_stack_, caller_stack_, jump_data);
456 jump_to(caller_, callee_stack_, callee_stack_, jump_data);
459 if (
nullptr != priv_data) {
469 #if defined(LIBCOPP_MACRO_ENABLE_WIN_FIBER) && LIBCOPP_MACRO_ENABLE_WIN_FIBER
477 LIBCOPP_COPP_API
int yield(
void **priv_data) LIBCOPP_MACRO_NOEXCEPT {
478 #if defined(LIBCOPP_MACRO_ENABLE_WIN_FIBER) && LIBCOPP_MACRO_ENABLE_WIN_FIBER
484 return pco->
yield(priv_data);
490 LIBCOPP_COPP_NAMESPACE_END
base type of all coroutine context
LIBCOPP_COPP_API ~coroutine_context_base()
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
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 LIBCOPP_COPP_API coroutine_context_base * get_this_coroutine_base() LIBCOPP_MACRO_NOEXCEPT
get current coroutine
LIBCOPP_COPP_API bool check_flags(int flags) const LIBCOPP_MACRO_NOEXCEPT
check flags
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
base type of all stackful coroutine context
LIBCOPP_COPP_API coroutine_context() LIBCOPP_MACRO_NOEXCEPT
fcontext::fcontext_t caller_
stack_context callee_stack_
LIBCOPP_COPP_API int start(void *priv_data=nullptr)
start coroutine
LIBCOPP_COPP_API int yield(void **priv_data=nullptr) LIBCOPP_MACRO_NOEXCEPT
yield coroutine
LIBCOPP_COPP_API ~coroutine_context()
LIBCOPP_COPP_API int resume(void *priv_data=nullptr)
resume coroutine
LIBCOPP_COPP_NAMESPACE_ID::util::lock::atomic_int_type< int > status_
fcontext::fcontext_t callee_
coroutine_context_base::callback_type callback_type
static LIBCOPP_COPP_API int create(coroutine_context *p, callback_type &&runner, const stack_context &callee_stack, size_t coroutine_size, size_t private_buffer_size) LIBCOPP_MACRO_NOEXCEPT
create coroutine context at stack context callee_
static void jump_to(fcontext::fcontext_t &to_fctx, EXPLICIT_UNUSED_ATTR stack_context &from_sctx, EXPLICIT_UNUSED_ATTR stack_context &to_sctx, libcopp_internal_api_set::jump_src_data_t &jump_transfer) LIBCOPP_MACRO_NOEXCEPT
call platform jump to asm instruction
@ COPP_EC_CAN_NOT_USE_CROSS_FCONTEXT_AND_FIBER
COPP_EC_CAN_NOT_USE_CROSS_FCONTEXT_AND_FIBER.
@ COPP_EC_SUCCESS
COPP_EC_SUCCESS.
@ COPP_EC_IS_RUNNING
COPP_EC_IS_RUNNING.
@ COPP_EC_FCONTEXT_MAKE_FAILED
COPP_EC_FCONTEXT_MAKE_FAILED.
@ COPP_EC_ALREADY_INITED
COPP_EC_ALREADY_INITED.
@ COPP_EC_NOT_READY
COPP_EC_NOT_READY.
@ COPP_EC_NOT_INITED
COPP_EC_NOT_INITED.
@ COPP_EC_UNKNOWN
COPP_EC_UNKNOWN.
@ COPP_EC_ALREADY_EXIST
COPP_EC_ALREADY_EXIST.
@ COPP_EC_ARGS_ERROR
COPP_EC_ARGS_ERROR.
@ COPP_EC_NOT_RUNNING
COPP_EC_NOT_RUNNING.
导入继承关系约束 Licensed under the MIT licenses.
#define EXPLICIT_UNUSED_ATTR
maybe_unused, 标记忽略unused警告 usage: EXPLICIT_UNUSED_ATTR int a; class EXPLICIT_UNUSED_ATTR a; EXPLICIT_...
#define COPP_UNLIKELY_IF(...)
#define COPP_LIKELY_IF(...)
static void set_this_coroutine_context(coroutine_context_base *p)
static pthread_key_t gt_coroutine_tls_key
static void init_pthread_this_coroutine_context()
static coroutine_context_base * get_this_coroutine_context()
static pthread_once_t gt_coroutine_init_once
COPP_BOOST_CONTEXT_DECL fcontext_t COPP_BOOST_CONTEXT_CALLDECL copp_make_fcontext_v2(void *sp, std::size_t size, void(*fn)(transfer_t))
COPP_BOOST_CONTEXT_DECL transfer_t COPP_BOOST_CONTEXT_CALLDECL copp_jump_fcontext_v2(fcontext_t const to, void *vp)
LIBCOPP_COPP_API int yield(void **priv_data=nullptr) LIBCOPP_MACRO_NOEXCEPT
yield current coroutine
LIBCOPP_COPP_API coroutine_context * get_coroutine() LIBCOPP_MACRO_NOEXCEPT
get current coroutine
void swap(intrusive_ptr< T > &lhs, intrusive_ptr< T > &rhs)
coroutine_context * from_co
coroutine_context * to_co
status of safe coroutine context base
@ EN_CRS_INVALID
EN_CRS_INVALID.
@ EN_CRS_READY
EN_CRS_READY.
@ EN_CRS_FINISHED
EN_CRS_FINISHED.
@ EN_CRS_EXITED
EN_CRS_EXITED.
@ EN_CRS_RUNNING
EN_CRS_RUNNING.
static void coroutine_context_callback(LIBCOPP_COPP_NAMESPACE_ID::fcontext::transfer_t src_ctx)
static UTIL_FORCEINLINE void set_caller(coroutine_context *src, const fcontext::fcontext_t &fctx)
static UTIL_FORCEINLINE void set_callee(coroutine_context *src, const fcontext::fcontext_t &fctx)