5 #include <libcopp/utils/config/libcopp_build_features.h>
20 #if defined(LIBCOPP_MACRO_ENABLE_WIN_FIBER) && LIBCOPP_MACRO_ENABLE_WIN_FIBER
21 LIBCOPP_COPP_NAMESPACE_BEGIN
26 template <
typename TALLOC>
27 class coroutine_context_fiber_container :
public coroutine_context_fiber {
29 using coroutine_context_type = coroutine_context_fiber;
30 using base_type = coroutine_context_fiber;
31 using allocator_type = TALLOC;
32 using this_type = coroutine_context_fiber_container<allocator_type>;
33 using ptr_type = LIBCOPP_COPP_NAMESPACE_ID::util::intrusive_ptr<this_type>;
34 using callback_type = coroutine_context_fiber::callback_type;
37 using ptr_t = ptr_type;
38 using callback_t = callback_type;
43 coroutine_context_fiber_container(
const allocator_type &alloc) LIBCOPP_MACRO_NOEXCEPT : alloc_(alloc),
46 coroutine_context_fiber_container(allocator_type &&alloc) LIBCOPP_MACRO_NOEXCEPT : alloc_(std::move(alloc)),
50 ~coroutine_context_fiber_container() {}
56 inline const allocator_type &get_allocator()
const LIBCOPP_MACRO_NOEXCEPT {
return alloc_; }
62 inline allocator_type &get_allocator() LIBCOPP_MACRO_NOEXCEPT {
return alloc_; }
73 static ptr_type create(callback_type &&runner, allocator_type &alloc,
size_t stack_sz = 0,
74 size_t private_buffer_size = 0,
size_t coroutine_size = 0) LIBCOPP_MACRO_NOEXCEPT {
81 coroutine_size = align_address_size(coroutine_size);
82 const size_t this_align_size = align_address_size(
sizeof(this_type));
83 coroutine_size += this_align_size;
84 private_buffer_size = coroutine_context_fiber::align_private_data_size(private_buffer_size);
88 alloc.allocate(callee_stack, coroutine_size + private_buffer_size);
90 if (
nullptr == callee_stack.
sp) {
95 unsigned char *this_addr =
reinterpret_cast<unsigned char *
>(callee_stack.
sp);
97 this_addr -= private_buffer_size + this_align_size;
98 ret.
reset(
new (
reinterpret_cast<void *
>(this_addr)) this_type(std::move(alloc)));
102 ret->callee_stack_ = std::move(callee_stack);
104 alloc.deallocate(callee_stack);
110 if (coroutine_context_fiber::create(ret.get(), std::move(runner), ret->callee_stack_, coroutine_size,
111 private_buffer_size, stack_sz) < 0) {
118 template <
class TRunner>
119 static inline ptr_type create(TRunner *runner, allocator_type &alloc,
size_t stack_size = 0,
120 size_t private_buffer_size = 0,
size_t coroutine_size = 0) LIBCOPP_MACRO_NOEXCEPT {
121 if (
nullptr == runner) {
122 return create(callback_type(), alloc, stack_size, private_buffer_size, coroutine_size);
125 return create([runner](
void *private_data) {
return (*runner)(private_data); }, alloc, stack_size,
126 private_buffer_size, coroutine_size);
129 static inline ptr_type create(
int (*fn)(
void *), allocator_type &alloc,
size_t stack_size = 0,
130 size_t private_buffer_size = 0,
size_t coroutine_size = 0) LIBCOPP_MACRO_NOEXCEPT {
132 return create(callback_type(), alloc, stack_size, private_buffer_size, coroutine_size);
135 return create(callback_type(fn), alloc, stack_size, private_buffer_size, coroutine_size);
138 static ptr_type create(callback_type &&runner,
size_t stack_size = 0,
size_t private_buffer_size = 0,
139 size_t coroutine_size = 0) LIBCOPP_MACRO_NOEXCEPT {
140 allocator_type alloc;
141 return create(std::move(runner), alloc, stack_size, private_buffer_size, coroutine_size);
144 template <
class TRunner>
145 static inline ptr_type create(TRunner *runner,
size_t stack_size = 0,
size_t private_buffer_size = 0,
146 size_t coroutine_size = 0) LIBCOPP_MACRO_NOEXCEPT {
147 return create([runner](
void *private_data) {
return (*runner)(private_data); }, stack_size, private_buffer_size,
151 static inline ptr_type create(
int (*fn)(
void *),
size_t stack_size = 0,
size_t private_buffer_size = 0,
152 size_t coroutine_size = 0) LIBCOPP_MACRO_NOEXCEPT {
153 return create(callback_type(fn), stack_size, private_buffer_size, coroutine_size);
156 inline size_t use_count()
const LIBCOPP_MACRO_NOEXCEPT {
return ref_count_.load(); }
159 coroutine_context_fiber_container(
const coroutine_context_fiber_container &) =
delete;
162 friend void intrusive_ptr_add_ref(this_type *p) {
170 friend void intrusive_ptr_release(this_type *p) {
175 size_t left = --p->ref_count_;
177 allocator_type copy_alloc(std::move(p->alloc_));
181 p->~coroutine_context_fiber_container();
184 copy_alloc.deallocate(copy_stack);
189 allocator_type alloc_;
190 # if defined(LIBCOPP_DISABLE_ATOMIC_LOCK) && LIBCOPP_DISABLE_ATOMIC_LOCK
191 LIBCOPP_COPP_NAMESPACE_ID::util::lock::atomic_int_type<
192 LIBCOPP_COPP_NAMESPACE_ID::util::lock::unsafe_int_type<size_t> >
195 LIBCOPP_COPP_NAMESPACE_ID::util::lock::atomic_int_type<size_t> ref_count_;
199 using coroutine_fiber_context_default = coroutine_context_fiber_container<allocator::stack_allocator_malloc>;
200 LIBCOPP_COPP_NAMESPACE_END
#define COROUTINE_CONTEXT_BASE_USING_BASE(base_type)
void reset() LIBCOPP_MACRO_NOEXCEPT
static LIBCOPP_COPP_API std::size_t default_size() LIBCOPP_MACRO_NOEXCEPT