Browse Source

generator_t的state也跟promise分配在一起。

tags/v2.9.7
tearshark 4 years ago
parent
commit
d1de24135f

+ 37
- 6
librf/src/generator.h View File

generator_iterator& operator++() generator_iterator& operator++()
{ {
_Coro.resume();
if (_Coro.done()) if (_Coro.done())
_Coro = nullptr; _Coro = nullptr;
else
_Coro.resume();
return *this; return *this;
} }
_Ty const* _CurrentValue; _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() promise_type& get_return_object()
{ {
return *this; return *this;
return std::forward<_Uty>(_Whatever); 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>; 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>, static_assert(std::is_same_v<char*, typename std::allocator_traits<_Alloc_char>::pointer>,
"generator_t does not support allocators with fancy pointer types"); "generator_t does not support allocators with fancy pointer types");
void* operator new(size_t _Size) 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; _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) 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; _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();
} }
}; };
} }
} }
coroutine_handle<promise_type> detach()
state_type* detach_state()
{ {
auto t = _Coro; auto t = _Coro;
_Coro = nullptr; _Coro = nullptr;
return t;
return t.promise().get_state();
} }
private: private:

+ 1
- 1
librf/src/promise.h View File

size_t _State_size = _Align_size<state_type>(); size_t _State_size = _Align_size<state_type>();
assert(_Size >= sizeof(uint32_t) && _Size < std::numeric_limits<uint32_t>::max() - sizeof(_State_size)); assert(_Size >= sizeof(uint32_t) && _Size < std::numeric_limits<uint32_t>::max() - sizeof(_State_size));
#if RESUMEF_DEBUG_COUNTER #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 #endif


_Alloc_char _Al; _Alloc_char _Al;

+ 1
- 1
librf/src/rf_task.h View File

protected: protected:
void initialize(future_type&& f) void initialize(future_type&& f)
{ {
_state = new state_type(f.detach());
_state = f.detach_state();
} }
}; };

+ 14
- 2
librf/src/state.cpp View File

void state_future_t::destroy_deallocate() void state_future_t::destroy_deallocate()
{ {
size_t _Size = this->_Alloc_size;
size_t _Size = this->_alloc_size;
#if RESUMEF_DEBUG_COUNTER #if RESUMEF_DEBUG_COUNTER
std::cout << "destroy_deallocate, size=" << _Size << std::endl; std::cout << "destroy_deallocate, size=" << _Size << std::endl;
#endif #endif
void state_generator_t::destroy_deallocate() 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() void state_generator_t::resume()
_coro.resume(); _coro.resume();
if (_coro.done()) if (_coro.done())
{ {
coroutine_handle<> handler = _coro;
_coro = nullptr; _coro = nullptr;
_scheduler->del_final(this); _scheduler->del_final(this);
handler.destroy();
} }
else else
{ {

+ 20
- 11
librf/src/state.h View File

struct state_base_t struct state_base_t
{ {
using _Alloc_char = std::allocator<char>; using _Alloc_char = std::allocator<char>;
RF_API virtual ~state_base_t();
private: private:
std::atomic<intptr_t> _count{0}; std::atomic<intptr_t> _count{0};
public: public:
// 一、经过co_await操作后,_coro在初始时不会为nullptr。 // 一、经过co_await操作后,_coro在初始时不会为nullptr。
// 二、没有co_await操作,直接加入到了调度器里,则_coro在初始时为nullptr。调度器需要特殊处理此种情况。 // 二、没有co_await操作,直接加入到了调度器里,则_coro在初始时为nullptr。调度器需要特殊处理此种情况。
coroutine_handle<> _coro; coroutine_handle<> _coro;
virtual ~state_base_t();
private: private:
virtual void destroy_deallocate() = 0; virtual void destroy_deallocate() = 0;
public: public:
struct state_generator_t : public state_base_t struct state_generator_t : public state_base_t
{ {
public:
state_generator_t(coroutine_handle<> handler) state_generator_t(coroutine_handle<> handler)
{ {
_coro = handler; _coro = handler;
} }
private:
virtual void destroy_deallocate() override; virtual void destroy_deallocate() override;
public:
virtual void resume() override; virtual void resume() override;
virtual bool has_handler() const override; virtual bool has_handler() const override;
virtual bool is_ready() 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 struct state_future_t : public state_base_t
intptr_t _id; intptr_t _id;
#endif #endif
std::exception_ptr _exception; std::exception_ptr _exception;
uint32_t _Alloc_size;
uint32_t _alloc_size;
bool _has_value = false; bool _has_value = false;
bool _is_awaitor; bool _is_awaitor;
bool _is_initor = false; bool _is_initor = false;
} }
void set_alloc_size(uint32_t val) void set_alloc_size(uint32_t val)
{ {
_Alloc_size = val;
_alloc_size = val;
} }
void set_exception(std::exception_ptr e); void set_exception(std::exception_ptr e);
state_t() :state_future_t() state_t() :state_future_t()
{ {
_Alloc_size = sizeof(*this);
_alloc_size = sizeof(*this);
} }
explicit state_t(bool awaitor) :state_future_t(awaitor) explicit state_t(bool awaitor) :state_future_t(awaitor)
{ {
_Alloc_size = sizeof(*this);
_alloc_size = sizeof(*this);
} }
private: private:
union union_value_type union union_value_type
~union_value_type() {} ~union_value_type() {}
}; };
union_value_type uv; union_value_type uv;
public:
~state_t() ~state_t()
{ {
if (_has_value) if (_has_value)
uv._value.~value_type(); uv._value.~value_type();
} }
public:
auto future_await_resume() -> value_type; auto future_await_resume() -> value_type;
template<class _PromiseT, typename = std::enable_if_t<is_promise_v<_PromiseT>>> template<class _PromiseT, typename = std::enable_if_t<is_promise_v<_PromiseT>>>
void promise_yield_value(_PromiseT* promise, value_type val); void promise_yield_value(_PromiseT* promise, value_type val);
state_t() :state_future_t() state_t() :state_future_t()
{ {
_Alloc_size = sizeof(*this);
_alloc_size = sizeof(*this);
} }
explicit state_t(bool awaitor) :state_future_t(awaitor) explicit state_t(bool awaitor) :state_future_t(awaitor)
{ {
_Alloc_size = sizeof(*this);
_alloc_size = sizeof(*this);
} }
public: public:
void future_await_resume(); void future_await_resume();

+ 5
- 0
tutorial/test_async_yield_return.cpp View File

void resumable_main_yield_return() void resumable_main_yield_return()
{ {
for (int i : test_yield_int())
{
std::cout << i << " had return" << std::endl;
}
go test_yield_int(); go test_yield_int();
this_scheduler()->run_until_notask(); this_scheduler()->run_until_notask();

+ 1
- 1
vs_proj/librf.cpp View File

{ {
(void)argc; (void)argc;
(void)argv; (void)argv;
resumable_main_routine();
resumable_main_yield_return();
//if (argc > 1) //if (argc > 1)
// resumable_main_benchmark_asio_client(atoi(argv[1])); // resumable_main_benchmark_asio_client(atoi(argv[1]));

Loading…
Cancel
Save