@@ -32,9 +32,10 @@ namespace resumef | |||
generator_iterator& operator++() | |||
{ | |||
_Coro.resume(); | |||
if (_Coro.done()) | |||
_Coro = nullptr; | |||
else | |||
_Coro.resume(); | |||
return *this; | |||
} | |||
@@ -106,6 +107,17 @@ namespace resumef | |||
_Ty const* _CurrentValue; | |||
promise_type() | |||
{ | |||
state_type* st = get_state(); | |||
new(st) state_type(coroutine_handle<promise_type>::from_promise(*this)); | |||
st->lock(); | |||
} | |||
promise_type(promise_type&& _Right) noexcept = default; | |||
promise_type& operator = (promise_type&& _Right) noexcept = default; | |||
promise_type(const promise_type&) = delete; | |||
promise_type& operator = (const promise_type&) = delete; | |||
promise_type& get_return_object() | |||
{ | |||
return *this; | |||
@@ -145,6 +157,13 @@ namespace resumef | |||
return std::forward<_Uty>(_Whatever); | |||
} | |||
state_type* get_state() | |||
{ | |||
size_t _State_size = _Align_size<state_type>(); | |||
char* ptr = reinterpret_cast<char*>(this) - _State_size; | |||
return reinterpret_cast<state_type*>(ptr); | |||
} | |||
using _Alloc_char = typename std::allocator_traits<_Alloc>::template rebind_alloc<char>; | |||
static_assert(std::is_same_v<char*, typename std::allocator_traits<_Alloc_char>::pointer>, | |||
"generator_t does not support allocators with fancy pointer types"); | |||
@@ -153,15 +172,27 @@ namespace resumef | |||
void* operator new(size_t _Size) | |||
{ | |||
size_t _State_size = _Align_size<state_type>(); | |||
assert(_Size >= sizeof(uint32_t) && _Size < std::numeric_limits<uint32_t>::max() - sizeof(_State_size)); | |||
#if RESUMEF_DEBUG_COUNTER | |||
std::cout << "generator_promise::new, size=" << (_Size + _State_size) << std::endl; | |||
#endif | |||
_Alloc_char _Al; | |||
void* ptr = _Al.allocate(_Size); | |||
return ptr; | |||
char* ptr = _Al.allocate(_Size + _State_size); | |||
return ptr + _State_size; | |||
} | |||
void operator delete(void* _Ptr, size_t _Size) | |||
{ | |||
size_t _State_size = _Align_size<state_type>(); | |||
assert(_Size >= sizeof(uint32_t) && _Size < std::numeric_limits<uint32_t>::max() - sizeof(_State_size)); | |||
*reinterpret_cast<uint32_t*>(_Ptr) = static_cast<uint32_t>(_Size + _State_size); | |||
_Alloc_char _Al; | |||
return _Al.deallocate(static_cast<char*>(_Ptr), _Size); | |||
state_type* st = reinterpret_cast<state_type*>(static_cast<char*>(_Ptr) - _State_size); | |||
st->unlock(); | |||
} | |||
}; | |||
@@ -216,11 +247,11 @@ namespace resumef | |||
} | |||
} | |||
coroutine_handle<promise_type> detach() | |||
state_type* detach_state() | |||
{ | |||
auto t = _Coro; | |||
_Coro = nullptr; | |||
return t; | |||
return t.promise().get_state(); | |||
} | |||
private: |
@@ -48,7 +48,7 @@ namespace resumef | |||
size_t _State_size = _Align_size<state_type>(); | |||
assert(_Size >= sizeof(uint32_t) && _Size < std::numeric_limits<uint32_t>::max() - sizeof(_State_size)); | |||
#if RESUMEF_DEBUG_COUNTER | |||
std::cout << "promise::new, size=" << (_Size + _State_size) << std::endl; | |||
std::cout << "future_promise::new, size=" << (_Size + _State_size) << std::endl; | |||
#endif | |||
_Alloc_char _Al; |
@@ -60,7 +60,7 @@ namespace resumef | |||
protected: | |||
void initialize(future_type&& f) | |||
{ | |||
_state = new state_type(f.detach()); | |||
_state = f.detach_state(); | |||
} | |||
}; | |||
@@ -11,7 +11,7 @@ namespace resumef | |||
void state_future_t::destroy_deallocate() | |||
{ | |||
size_t _Size = this->_Alloc_size; | |||
size_t _Size = this->_alloc_size; | |||
#if RESUMEF_DEBUG_COUNTER | |||
std::cout << "destroy_deallocate, size=" << _Size << std::endl; | |||
#endif | |||
@@ -23,7 +23,16 @@ namespace resumef | |||
void state_generator_t::destroy_deallocate() | |||
{ | |||
delete this; | |||
size_t _Size = _Align_size<state_generator_t>(); | |||
char* _Ptr = reinterpret_cast<char*>(this) + _Size; | |||
_Size = *reinterpret_cast<uint32_t*>(_Ptr); | |||
#if RESUMEF_DEBUG_COUNTER | |||
std::cout << "destroy_deallocate, size=" << _Size << std::endl; | |||
#endif | |||
this->~state_generator_t(); | |||
_Alloc_char _Al; | |||
return _Al.deallocate(reinterpret_cast<char*>(this), _Size); | |||
} | |||
void state_generator_t::resume() | |||
@@ -33,8 +42,11 @@ namespace resumef | |||
_coro.resume(); | |||
if (_coro.done()) | |||
{ | |||
coroutine_handle<> handler = _coro; | |||
_coro = nullptr; | |||
_scheduler->del_final(this); | |||
handler.destroy(); | |||
} | |||
else | |||
{ |
@@ -11,8 +11,6 @@ namespace resumef | |||
struct state_base_t | |||
{ | |||
using _Alloc_char = std::allocator<char>; | |||
RF_API virtual ~state_base_t(); | |||
private: | |||
std::atomic<intptr_t> _count{0}; | |||
public: | |||
@@ -34,6 +32,8 @@ namespace resumef | |||
// 一、经过co_await操作后,_coro在初始时不会为nullptr。 | |||
// 二、没有co_await操作,直接加入到了调度器里,则_coro在初始时为nullptr。调度器需要特殊处理此种情况。 | |||
coroutine_handle<> _coro; | |||
virtual ~state_base_t(); | |||
private: | |||
virtual void destroy_deallocate() = 0; | |||
public: | |||
@@ -53,16 +53,24 @@ namespace resumef | |||
struct state_generator_t : public state_base_t | |||
{ | |||
public: | |||
state_generator_t(coroutine_handle<> handler) | |||
{ | |||
_coro = handler; | |||
} | |||
private: | |||
virtual void destroy_deallocate() override; | |||
public: | |||
virtual void resume() override; | |||
virtual bool has_handler() const override; | |||
virtual bool is_ready() const override; | |||
static state_generator_t * _Alloc_state(coroutine_handle<> handler) | |||
{ | |||
#if RESUMEF_DEBUG_COUNTER | |||
std::cout << "state_generator_t::alloc, size=" << sizeof(state_generator_t) << std::endl; | |||
#endif | |||
return new state_generator_t(handler); | |||
} | |||
}; | |||
struct state_future_t : public state_base_t | |||
@@ -76,7 +84,7 @@ namespace resumef | |||
intptr_t _id; | |||
#endif | |||
std::exception_ptr _exception; | |||
uint32_t _Alloc_size; | |||
uint32_t _alloc_size; | |||
bool _has_value = false; | |||
bool _is_awaitor; | |||
bool _is_initor = false; | |||
@@ -112,7 +120,7 @@ namespace resumef | |||
} | |||
void set_alloc_size(uint32_t val) | |||
{ | |||
_Alloc_size = val; | |||
_alloc_size = val; | |||
} | |||
void set_exception(std::exception_ptr e); | |||
@@ -146,11 +154,11 @@ namespace resumef | |||
state_t() :state_future_t() | |||
{ | |||
_Alloc_size = sizeof(*this); | |||
_alloc_size = sizeof(*this); | |||
} | |||
explicit state_t(bool awaitor) :state_future_t(awaitor) | |||
{ | |||
_Alloc_size = sizeof(*this); | |||
_alloc_size = sizeof(*this); | |||
} | |||
private: | |||
union union_value_type | |||
@@ -162,12 +170,13 @@ namespace resumef | |||
~union_value_type() {} | |||
}; | |||
union_value_type uv; | |||
public: | |||
~state_t() | |||
{ | |||
if (_has_value) | |||
uv._value.~value_type(); | |||
} | |||
public: | |||
auto future_await_resume() -> value_type; | |||
template<class _PromiseT, typename = std::enable_if_t<is_promise_v<_PromiseT>>> | |||
void promise_yield_value(_PromiseT* promise, value_type val); | |||
@@ -182,11 +191,11 @@ namespace resumef | |||
state_t() :state_future_t() | |||
{ | |||
_Alloc_size = sizeof(*this); | |||
_alloc_size = sizeof(*this); | |||
} | |||
explicit state_t(bool awaitor) :state_future_t(awaitor) | |||
{ | |||
_Alloc_size = sizeof(*this); | |||
_alloc_size = sizeof(*this); | |||
} | |||
public: | |||
void future_await_resume(); |
@@ -59,6 +59,11 @@ auto test_yield_void() -> generator_t<> | |||
void resumable_main_yield_return() | |||
{ | |||
for (int i : test_yield_int()) | |||
{ | |||
std::cout << i << " had return" << std::endl; | |||
} | |||
go test_yield_int(); | |||
this_scheduler()->run_until_notask(); | |||
@@ -31,7 +31,7 @@ int main(int argc, const char* argv[]) | |||
{ | |||
(void)argc; | |||
(void)argv; | |||
resumable_main_routine(); | |||
resumable_main_yield_return(); | |||
//if (argc > 1) | |||
// resumable_main_benchmark_asio_client(atoi(argv[1])); |