Browse Source

将异常和返回值做成union以减小state的大小。

支持返回引用。
tags/v2.9.7
tearshark 4 years ago
parent
commit
837a2827ba

+ 1
- 1
benchmark/benchmark_channel_passing_next.cpp View File

for (;;) for (;;)
{ {
intptr_t value = co_await *rd; intptr_t value = co_await *rd;
co_await (*wr << (value + 1));
co_await wr->write(value + 1);
} }
} }



+ 15
- 2
librf/src/awaitable.h View File

}; };


template<class _Ty> template<class _Ty>
struct awaitable_t : public awaitable_impl_t<_Ty>
struct [[nodiscard]] awaitable_t : public awaitable_impl_t<_Ty>
{ {
using typename awaitable_impl_t<_Ty>::value_type; using typename awaitable_impl_t<_Ty>::value_type;
using awaitable_impl_t<_Ty>::awaitable_impl_t; using awaitable_impl_t<_Ty>::awaitable_impl_t;
} }
}; };


template<class _Ty>
struct [[nodiscard]] awaitable_t<_Ty&> : public awaitable_impl_t<_Ty&>
{
using typename awaitable_impl_t<_Ty&>::value_type;
using awaitable_impl_t<_Ty&>::awaitable_impl_t;

void set_value(_Ty& value) const
{
this->_state->set_value(value);
this->_state = nullptr;
}
};

template<> template<>
struct awaitable_t<void> : public awaitable_impl_t<void>
struct [[nodiscard]] awaitable_t<void> : public awaitable_impl_t<void>
{ {
using awaitable_impl_t<void>::awaitable_impl_t; using awaitable_impl_t<void>::awaitable_impl_t;



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

#pragma once #pragma once
#define LIB_RESUMEF_VERSION 20303 // 2.3.3
#define LIB_RESUMEF_VERSION 20304 // 2.3.4
#if defined(RESUMEF_MODULE_EXPORT) #if defined(RESUMEF_MODULE_EXPORT)
#define RESUMEF_NS export namespace resumef #define RESUMEF_NS export namespace resumef

+ 57
- 0
librf/src/event.cpp View File

return awaitable.get_future(); return awaitable.get_future();
} }
void async_manual_reset_event::set() noexcept
{
// Needs to be 'release' so that subsequent 'co_await' has
// visibility of our prior writes.
// Needs to be 'acquire' so that we have visibility of prior
// writes by awaiting coroutines.
void* oldValue = m_state.exchange(this, std::memory_order_acq_rel);
if (oldValue != this)
{
// Wasn't already in 'set' state.
// Treat old value as head of a linked-list of waiters
// which we have now acquired and need to resume.
auto* waiters = static_cast<awaiter*>(oldValue);
while (waiters != nullptr)
{
// Read m_next before resuming the coroutine as resuming
// the coroutine will likely destroy the awaiter object.
auto* next = waiters->m_next;
waiters->m_awaitingCoroutine.resume();
waiters = next;
}
}
}
bool async_manual_reset_event::awaiter::await_suspend(
coroutine_handle<> awaitingCoroutine) noexcept
{
// Special m_state value that indicates the event is in the 'set' state.
const void* const setState = &m_event;
// Remember the handle of the awaiting coroutine.
m_awaitingCoroutine = awaitingCoroutine;
// Try to atomically push this awaiter onto the front of the list.
void* oldValue = m_event.m_state.load(std::memory_order_acquire);
do
{
// Resume immediately if already in 'set' state.
if (oldValue == setState) return false;
// Update linked list to point at current head.
m_next = static_cast<awaiter*>(oldValue);
// Finally, try to swap the old list head, inserting this awaiter
// as the new list head.
} while (!m_event.m_state.compare_exchange_weak(
oldValue,
this,
std::memory_order_release,
std::memory_order_acquire));
// Successfully enqueued. Remain suspended.
return true;
}
} }

+ 59
- 0
librf/src/event.h View File

static future_t<bool> wait_all_until_(const clock_type::time_point& tp, std::vector<event_impl_ptr>&& evts); static future_t<bool> wait_all_until_(const clock_type::time_point& tp, std::vector<event_impl_ptr>&& evts);
}; };
class async_manual_reset_event
{
public:
async_manual_reset_event(bool initiallySet = false) noexcept
: m_state(initiallySet ? this : nullptr)
{}
// No copying/moving
async_manual_reset_event(const async_manual_reset_event&) = delete;
async_manual_reset_event(async_manual_reset_event&&) = delete;
async_manual_reset_event& operator=(const async_manual_reset_event&) = delete;
async_manual_reset_event& operator=(async_manual_reset_event&&) = delete;
bool is_set() const noexcept
{
return m_state.load(std::memory_order_acquire) == this;
}
struct awaiter;
awaiter operator co_await() const noexcept;
void set() noexcept;
void reset() noexcept
{
void* oldValue = this;
m_state.compare_exchange_strong(oldValue, nullptr, std::memory_order_acquire);
}
private:
friend struct awaiter;
// - 'this' => set state
// - otherwise => not set, head of linked list of awaiter*.
mutable std::atomic<void*> m_state;
};
struct async_manual_reset_event::awaiter
{
awaiter(const async_manual_reset_event& event) noexcept
: m_event(event)
{}
bool await_ready() const noexcept
{
return m_event.is_set();
}
bool await_suspend(coroutine_handle<> awaitingCoroutine) noexcept;
void await_resume() noexcept {}
private:
friend class async_manual_reset_event;
const async_manual_reset_event& m_event;
coroutine_handle<> m_awaitingCoroutine;
awaiter* m_next;
};
inline async_manual_reset_event::awaiter async_manual_reset_event::operator co_await() const noexcept
{
return awaiter{ *this };
}
} }

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

RESUMEF_NS RESUMEF_NS
{ {
template<class _Ty> template<class _Ty>
struct future_t
struct [[nodiscard]] future_t
{ {
using value_type = _Ty; using value_type = _Ty;
using state_type = state_t<value_type>; using state_type = state_t<value_type>;

+ 10
- 0
librf/src/promise.h View File

std::experimental::suspend_always yield_value(U&& val); std::experimental::suspend_always yield_value(U&& val);
}; };


template<class _Ty>
struct promise_t<_Ty&> final : public promise_impl_t<_Ty&>
{
using typename promise_impl_t<_Ty&>::value_type;
using promise_impl_t<_Ty&>::get_return_object;

void return_value(_Ty& val); //co_return val
std::experimental::suspend_always yield_value(_Ty& val);
};

template<> template<>
struct promise_t<void> final : public promise_impl_t<void> struct promise_t<void> final : public promise_impl_t<void>
{ {

+ 13
- 0
librf/src/promise.inl View File

return {}; return {};
} }


template<class _Ty>
inline void promise_t<_Ty&>::return_value(_Ty& val)
{
this->get_state()->set_value(val);
}

template<class _Ty>
inline std::experimental::suspend_always promise_t<_Ty&>::yield_value(_Ty& val)
{
this->get_state()->promise_yield_value(this, val);
return {};
}

inline void promise_t<void>::return_void() inline void promise_t<void>::return_void()
{ {
this->get_state()->set_value(); this->get_state()->set_value();

+ 17
- 17
librf/src/state.cpp View File

return has_handler_skip_lock(); return has_handler_skip_lock();
} }
void state_future_t::set_exception(std::exception_ptr e)
{
scoped_lock<lock_type> __guard(this->_mtx);
this->_exception = std::move(e);
scheduler_t* sch = this->get_scheduler();
if (sch != nullptr)
{
if (this->has_handler_skip_lock())
sch->add_generator(this);
else
sch->del_final(this);
}
}
bool state_future_t::switch_scheduler_await_suspend(scheduler_t* sch, coroutine_handle<> handler) bool state_future_t::switch_scheduler_await_suspend(scheduler_t* sch, coroutine_handle<> handler)
{ {
assert(sch != nullptr); assert(sch != nullptr);
if (this->_exception) if (this->_exception)
std::rethrow_exception(std::move(this->_exception)); std::rethrow_exception(std::move(this->_exception));
if (!this->_has_value.load(std::memory_order_acquire))
if (this->_has_value.load(std::memory_order_acquire) == result_type::None)
std::rethrow_exception(std::make_exception_ptr(future_exception{error_code::not_ready})); std::rethrow_exception(std::make_exception_ptr(future_exception{error_code::not_ready}));
} }
void state_t<void>::set_value() void state_t<void>::set_value()
{ {
scoped_lock<lock_type> __guard(this->_mtx); scoped_lock<lock_type> __guard(this->_mtx);
this->_has_value.store(true, std::memory_order_release);
this->_has_value.store(result_type::Value, std::memory_order_release);
scheduler_t* sch = this->get_scheduler();
if (sch != nullptr)
{
if (this->has_handler_skip_lock())
sch->add_generator(this);
else
sch->del_final(this);
}
}
void state_t<void>::set_exception(std::exception_ptr e)
{
scoped_lock<lock_type> __guard(this->_mtx);
this->_exception = std::move(e);
scheduler_t* sch = this->get_scheduler(); scheduler_t* sch = this->get_scheduler();
if (sch != nullptr) if (sch != nullptr)

+ 90
- 17
librf/src/state.h View File

Initial, Initial,
Final Final
}; };
enum struct result_type : uint8_t
{
None,
Value,
Exception,
};
//typedef std::recursive_mutex lock_type; //typedef std::recursive_mutex lock_type;
typedef spinlock lock_type; typedef spinlock lock_type;
protected: protected:
#if RESUMEF_DEBUG_COUNTER #if RESUMEF_DEBUG_COUNTER
intptr_t _id; intptr_t _id;
#endif #endif
std::exception_ptr _exception;
uint32_t _alloc_size = 0; uint32_t _alloc_size = 0;
std::atomic<bool> _has_value{ false };
std::atomic<result_type> _has_value{ result_type::None };
bool _is_awaitor; bool _is_awaitor;
initor_type _is_initor = initor_type::None; initor_type _is_initor = initor_type::None;
public: public:
inline bool is_ready() const inline bool is_ready() const
{ {
return _exception != nullptr || _has_value.load(std::memory_order_acquire) || !_is_awaitor;
return _has_value.load(std::memory_order_acquire) != result_type::None || !_is_awaitor;
} }
inline bool has_handler_skip_lock() const inline bool has_handler_skip_lock() const
{ {
return _alloc_size; return _alloc_size;
} }
void set_exception(std::exception_ptr e);
template<class _Exp>
inline void throw_exception(_Exp e)
{
set_exception(std::make_exception_ptr(std::move(e)));
}
inline bool future_await_ready() inline bool future_await_ready()
{ {
//scoped_lock<lock_type> __guard(this->_mtx); //scoped_lock<lock_type> __guard(this->_mtx);
return _has_value.load(std::memory_order_acquire);
return _has_value.load(std::memory_order_acquire) != result_type::None;
} }
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 future_await_suspend(coroutine_handle<_PromiseT> handler); void future_await_suspend(coroutine_handle<_PromiseT> handler);
public: public:
~state_t() ~state_t()
{ {
if (_has_value.load(std::memory_order_acquire))
cast_value_ptr()->~value_type();
switch (_has_value.load(std::memory_order_acquire))
{
case result_type::Value:
_value.~value_type();
break;
case result_type::Exception:
_exception.~exception_ptr();
break;
default:
break;
}
} }
auto future_await_resume() -> value_type; auto future_await_resume() -> value_type;
template<class _PromiseT, typename U, typename = std::enable_if_t<is_promise_v<_PromiseT>>> template<class _PromiseT, typename U, typename = std::enable_if_t<is_promise_v<_PromiseT>>>
void promise_yield_value(_PromiseT* promise, U&& val); void promise_yield_value(_PromiseT* promise, U&& val);
void set_exception(std::exception_ptr e);
template<typename U> template<typename U>
void set_value(U&& val); void set_value(U&& val);
template<class _Exp>
inline void throw_exception(_Exp e)
{
set_exception(std::make_exception_ptr(std::move(e)));
}
private: private:
value_type * cast_value_ptr()
union
{ {
return static_cast<value_type*>(static_cast<void*>(_value));
std::exception_ptr _exception;
value_type _value;
};
template<typename U>
void set_value_internal(U&& val);
void set_exception_internal(std::exception_ptr e);
};
template <typename _Ty>
struct state_t<_Ty&> final : public state_future_t
{
friend state_future_t;
using state_future_t::lock_type;
using value_type = _Ty;
using reference_type = _Ty&;
explicit state_t(size_t alloc_size) :state_future_t()
{
_alloc_size = static_cast<uint32_t>(alloc_size);
} }
explicit state_t(bool awaitor) :state_future_t(awaitor)
{
_alloc_size = sizeof(*this);
}
public:
~state_t()
{
if (_has_value.load(std::memory_order_acquire) == result_type::Exception)
_exception.~exception_ptr();
}
auto future_await_resume()->reference_type;
template<class _PromiseT, typename = std::enable_if_t<is_promise_v<_PromiseT>>>
void promise_yield_value(_PromiseT* promise, reference_type val);
alignas(value_type) unsigned char _value[sizeof(value_type)] = {0};
void set_exception(std::exception_ptr e);
void set_value(reference_type val);
template<class _Exp>
inline void throw_exception(_Exp e)
{
set_exception(std::make_exception_ptr(std::move(e)));
}
private:
union
{
std::exception_ptr _exception;
value_type* _value;
};
void set_value_internal(reference_type val);
void set_exception_internal(std::exception_ptr e);
}; };
template<> template<>
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); void promise_yield_value(_PromiseT* promise);
void set_exception(std::exception_ptr e);
void set_value(); void set_value();
template<class _Exp>
inline void throw_exception(_Exp e)
{
set_exception(std::make_exception_ptr(std::move(e)));
}
private:
std::exception_ptr _exception;
}; };
} }

+ 172
- 19
librf/src/state.inl View File

sch->add_generator(this); sch->add_generator(this);
} }


//------------------------------------------------------------------------------------------------

template<class _PromiseT, typename _Enable > template<class _PromiseT, typename _Enable >
void state_t<void>::promise_yield_value(_PromiseT* promise) void state_t<void>::promise_yield_value(_PromiseT* promise)
{ {
this->_coro = handler; this->_coro = handler;
} }


this->_has_value.store(true, std::memory_order_release);
this->_has_value.store(result_type::Value, std::memory_order_release);


if (!handler.done()) if (!handler.done())
{ {
} }
} }


//------------------------------------------------------------------------------------------------

template<typename _Ty> template<typename _Ty>
template<class _PromiseT, typename U, typename _Enable > template<class _PromiseT, typename U, typename _Enable >
void state_t<_Ty>::promise_yield_value(_PromiseT* promise, U&& val) void state_t<_Ty>::promise_yield_value(_PromiseT* promise, U&& val)
this->_coro = handler; this->_coro = handler;
} }


if (this->_has_value.load(std::memory_order_acquire))
{
*this->cast_value_ptr() = std::forward<U>(val);
}
else
{
new (this->cast_value_ptr()) value_type(std::forward<U>(val));
this->_has_value.store(true, std::memory_order_release);
}
set_value_internal(std::forward<U>(val));


if (!handler.done()) if (!handler.done())
{ {
auto state_t<_Ty>::future_await_resume() -> value_type auto state_t<_Ty>::future_await_resume() -> value_type
{ {
scoped_lock<lock_type> __guard(this->_mtx); scoped_lock<lock_type> __guard(this->_mtx);
if (this->_exception)

switch (this->_has_value.load(std::memory_order_acquire))
{
case result_type::None:
std::rethrow_exception(std::make_exception_ptr(future_exception{ error_code::not_ready }));
break;
case result_type::Exception:
std::rethrow_exception(std::move(this->_exception)); std::rethrow_exception(std::move(this->_exception));
if (!this->_has_value.load(std::memory_order_acquire))
std::rethrow_exception(std::make_exception_ptr(future_exception{error_code::not_ready}));
break;
default:
break;
}

return std::move(this->_value);
}

template<typename _Ty>
template<typename U>
void state_t<_Ty>::set_value_internal(U&& val)
{
switch (_has_value.load(std::memory_order_acquire))
{
case result_type::Value:
_value = std::forward<U>(val);
break;
case result_type::Exception:
_exception.~exception_ptr();
default:
new (&this->_value) value_type(std::forward<U>(val));
this->_has_value.store(result_type::Value, std::memory_order_release);
break;
}
}


return std::move(*this->cast_value_ptr());
template<typename _Ty>
void state_t<_Ty>::set_exception_internal(std::exception_ptr e)
{
switch (_has_value.load(std::memory_order_acquire))
{
case result_type::Exception:
_exception = std::move(e);
break;
case result_type::Value:
_value.~value_type();
default:
new (&this->_exception) std::exception_ptr(std::move(e));
this->_has_value.store(result_type::Exception, std::memory_order_release);
break;
}
} }


template<typename _Ty> template<typename _Ty>
void state_t<_Ty>::set_value(U&& val) void state_t<_Ty>::set_value(U&& val)
{ {
scoped_lock<lock_type> __guard(this->_mtx); scoped_lock<lock_type> __guard(this->_mtx);
set_value_internal(std::forward<U>(val));

scheduler_t* sch = this->get_scheduler();
if (sch != nullptr)
{
if (this->has_handler_skip_lock())
sch->add_generator(this);
else
sch->del_final(this);
}
}

template<typename _Ty>
void state_t<_Ty>::set_exception(std::exception_ptr e)
{
scoped_lock<lock_type> __guard(this->_mtx);
set_exception_internal(std::move(e));

scheduler_t* sch = this->get_scheduler();
if (sch != nullptr)
{
if (this->has_handler_skip_lock())
sch->add_generator(this);
else
sch->del_final(this);
}
}

//------------------------------------------------------------------------------------------------

template<typename _Ty>
template<class _PromiseT, typename _Enable >
void state_t<_Ty&>::promise_yield_value(_PromiseT* promise, reference_type val)
{
coroutine_handle<_PromiseT> handler = coroutine_handle<_PromiseT>::from_promise(*promise);

scoped_lock<lock_type> __guard(this->_mtx);

if (!handler.done())
{
if (this->_coro == nullptr)
this->_coro = handler;
}

set_value_internal(val);

if (!handler.done())
{
scheduler_t* sch = this->get_scheduler();
if (sch != nullptr)
sch->add_generator(this);
}
}

template<typename _Ty>
auto state_t<_Ty&>::future_await_resume() -> reference_type
{
scoped_lock<lock_type> __guard(this->_mtx);

switch (this->_has_value.load(std::memory_order_acquire))
{
case result_type::None:
std::rethrow_exception(std::make_exception_ptr(future_exception{ error_code::not_ready }));
break;
case result_type::Exception:
std::rethrow_exception(std::move(this->_exception));
break;
default:
break;
}

return static_cast<reference_type>(*this->_value);
}


if (this->_has_value.load(std::memory_order_acquire))
template<typename _Ty>
void state_t<_Ty&>::set_value_internal(reference_type val)
{
switch (_has_value.load(std::memory_order_acquire))
{ {
*this->cast_value_ptr() = std::forward<U>(val);
case result_type::Exception:
_exception.~exception_ptr();
default:
this->_value = &val;
this->_has_value.store(result_type::Value, std::memory_order_release);
break;
} }
else
}

template<typename _Ty>
void state_t<_Ty&>::set_exception_internal(std::exception_ptr e)
{
switch (_has_value.load(std::memory_order_acquire))
{
case result_type::Exception:
_exception = std::move(e);
break;
default:
new (&this->_exception) std::exception_ptr(std::move(e));
this->_has_value.store(result_type::Exception, std::memory_order_release);
break;
}
}

template<typename _Ty>
void state_t<_Ty&>::set_value(reference_type val)
{
scoped_lock<lock_type> __guard(this->_mtx);
set_value_internal(val);

scheduler_t* sch = this->get_scheduler();
if (sch != nullptr)
{ {
new (this->cast_value_ptr()) value_type(std::forward<U>(val));
this->_has_value.store(true, std::memory_order_release);
if (this->has_handler_skip_lock())
sch->add_generator(this);
else
sch->del_final(this);
} }
}

template<typename _Ty>
void state_t<_Ty&>::set_exception(std::exception_ptr e)
{
scoped_lock<lock_type> __guard(this->_mtx);
set_exception_internal(std::move(e));


scheduler_t* sch = this->get_scheduler(); scheduler_t* sch = this->get_scheduler();
if (sch != nullptr) if (sch != nullptr)

+ 30
- 3
tutorial/test_async_cb.cpp View File

//这种情况下,没有生成 frame-context,因此,并没有promise_type被内嵌在frame-context里 //这种情况下,没有生成 frame-context,因此,并没有promise_type被内嵌在frame-context里
static future_t<int64_t> async_get_long(int64_t val) static future_t<int64_t> async_get_long(int64_t val)
{ {
resumef::awaitable_t<int64_t> awaitable;
awaitable_t<int64_t> awaitable;
callback_get_long(val, [awaitable](int64_t val) callback_get_long(val, [awaitable](int64_t val)
{ {
awaitable.set_value(val); awaitable.set_value(val);
co_return val; co_return val;
} }
static future_t<std::string&> async_get_string(std::string & ref_string)
{
awaitable_t<std::string&> awaitable;
callback_get_long(std::stoi(ref_string), [awaitable, &ref_string](int64_t val)
{
ref_string = std::to_string(val);
awaitable.set_value(ref_string);
});
return awaitable.get_future();
}
static future_t<std::string&> resumable_get_string(std::string& val)
{
std::cout << val << std::endl;
val = co_await async_get_string(val);
std::cout << val << std::endl;
val = co_await async_get_string(val);
std::cout << val << std::endl;
val = co_await async_get_string(val);
std::cout << val << std::endl;
co_return static_cast<std::string&>(val);
}
void resumable_main_cb() void resumable_main_cb()
{ {
//由于使用者可能不能明确的区分是resume function返回的awaitor还是awaitable function返回的awaitor //由于使用者可能不能明确的区分是resume function返回的awaitor还是awaitable function返回的awaitor
//导致均有可能加入到协程里去调度。 //导致均有可能加入到协程里去调度。
//所以,协程调度器应该需要能处理这种情况。 //所以,协程调度器应该需要能处理这种情况。
go async_get_long(3); go async_get_long(3);
resumef::this_scheduler()->run_until_notask();
this_scheduler()->run_until_notask();
std::string ref_string{"2"};
go resumable_get_string(ref_string);
this_scheduler()->run_until_notask();
GO GO
{ {
}; };
go loop_get_long(3); go loop_get_long(3);
resumef::this_scheduler()->run_until_notask();
this_scheduler()->run_until_notask();
} }

+ 6
- 6
tutorial/test_async_memory_layout.cpp View File

promise_type* promise = &handler.promise(); promise_type* promise = &handler.promise();
state_type* state = handler.promise().get_state(); state_type* state = handler.promise().get_state();


std::cout << " future size=" << _Align_size<future_type>() << std::endl;
std::cout << " promise size=" << _Align_size<promise_type>() << std::endl;
std::cout << " state size=" << _Align_size<state_type>() << std::endl;
std::cout << " future size=" << sizeof(future_type) << " / " << _Align_size<future_type>() << std::endl;
std::cout << " promise size=" << sizeof(promise_type) << " / " << _Align_size<promise_type>() << std::endl;
std::cout << " state size=" << sizeof(state_type) << " / "<< _Align_size<state_type>() << std::endl;
std::cout << " frame size=" << _coro_frame_size() << ", alloc size=" << state->get_alloc_size() << std::endl; std::cout << " frame size=" << _coro_frame_size() << ", alloc size=" << state->get_alloc_size() << std::endl;


std::cout << " frame ptr=" << frame_ptr << "," << (void*)&frame_ptr << std::endl; std::cout << " frame ptr=" << frame_ptr << "," << (void*)&frame_ptr << std::endl;
promise_type * promise = &handler.promise(); promise_type * promise = &handler.promise();
state_type * state = handler.promise().get_state(); state_type * state = handler.promise().get_state();


std::cout << " future size=" << _Align_size<future_type>() << std::endl;
std::cout << " promise size=" << _Align_size<promise_type>() << std::endl;
std::cout << " state size=" << _Align_size<state_type>() << std::endl;
std::cout << " future size=" << sizeof(future_type) << " / " << _Align_size<future_type>() << std::endl;
std::cout << " promise size=" << sizeof(promise_type) << " / " << _Align_size<promise_type>() << std::endl;
std::cout << " state size=" << sizeof(state_type) << " / "<< _Align_size<state_type>() << std::endl;
std::cout << " frame size=" << _coro_frame_size() << ", alloc size=" << state->get_alloc_size() << std::endl; std::cout << " frame size=" << _coro_frame_size() << ", alloc size=" << state->get_alloc_size() << std::endl;


std::cout << " frame ptr=" << frame_ptr << ","<< (void*)&frame_ptr << std::endl; std::cout << " frame ptr=" << frame_ptr << ","<< (void*)&frame_ptr << std::endl;

+ 1
- 1
tutorial/test_async_sleep.cpp View File

{ {
using namespace std::chrono; using namespace std::chrono;
resumef::sleep_for(100ms); //incorrect!!!
(void)resumef::sleep_for(100ms); //incorrect!!!
co_await resumef::sleep_for(100ms); co_await resumef::sleep_for(100ms);
std::cout << "sleep_for 100ms." << std::endl; std::cout << "sleep_for 100ms." << std::endl;

+ 2
- 2
tutorial/test_async_switch_scheduler.cpp View File

local_scheduler my_scheduler; //产生本线程唯一的调度器 local_scheduler my_scheduler; //产生本线程唯一的调度器
sch_in_thread = this_scheduler(); //本线程唯一的调度器赋值给sch_in_thread,以便于后续测试直接访问此线程的调度器 sch_in_thread = this_scheduler(); //本线程唯一的调度器赋值给sch_in_thread,以便于后续测试直接访问此线程的调度器


c_done << true; //数据都准备好了,通过channel通知其他协程可以启动后续依赖sch_in_thread变量的协程了
(void)c_done.write(true); //数据都准备好了,通过channel通知其他协程可以启动后续依赖sch_in_thread变量的协程了


//循环直到sch_in_thread为nullptr //循环直到sch_in_thread为nullptr
for (;;) for (;;)
val = co_await async_get_long(val); val = co_await async_get_long(val);
std::cout << "thread = " << std::this_thread::get_id() << ", value = " << val << std::endl; std::cout << "thread = " << std::this_thread::get_id() << ", value = " << val << std::endl;


c_done << true;
(void)c_done.write(true);
} }


void resumable_main_switch_scheduler() void resumable_main_switch_scheduler()

+ 3
- 1
vs_proj/librf.cpp View File

{ {
(void)argc; (void)argc;
(void)argv; (void)argv;
//resumable_main_resumable();
//resumable_main_layout();
//return 0; //return 0;
//if (argc > 1) //if (argc > 1)
resumable_main_switch_scheduler(); resumable_main_switch_scheduler();
std::cout << "ALL OK!" << std::endl; std::cout << "ALL OK!" << std::endl;
#if !defined(__clang__) || defined(_WIN64)
benchmark_main_channel_passing_next(); //这是一个死循环测试 benchmark_main_channel_passing_next(); //这是一个死循环测试
#endif
return 0; return 0;
} }

+ 13
- 12
vs_proj/librf.vcxproj View File

<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType> <ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries> <UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<PlatformToolset>ClangCL</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization> <WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>NotSet</CharacterSet> <CharacterSet>NotSet</CharacterSet>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType> <ConfigurationType>Application</ConfigurationType>
<PlatformToolset>v142</PlatformToolset>
<PlatformToolset>ClangCL</PlatformToolset>
<UseDebugLibraries>true</UseDebugLibraries> <UseDebugLibraries>true</UseDebugLibraries>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType> <ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries> <UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<PlatformToolset>ClangCL</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization> <WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>NotSet</CharacterSet> <CharacterSet>NotSet</CharacterSet>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental> <LinkIncremental>true</LinkIncremental>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<CodeAnalysisRuleSet>NativeRecommendedRules.ruleset</CodeAnalysisRuleSet> <CodeAnalysisRuleSet>NativeRecommendedRules.ruleset</CodeAnalysisRuleSet>
<EnableClangTidyCodeAnalysis>true</EnableClangTidyCodeAnalysis> <EnableClangTidyCodeAnalysis>true</EnableClangTidyCodeAnalysis>
<CLanguageStandard>c11</CLanguageStandard> <CLanguageStandard>c11</CLanguageStandard>
<CppLanguageStandard>c++1y</CppLanguageStandard> <CppLanguageStandard>c++1y</CppLanguageStandard>
<DisableSpecificWarnings>4834</DisableSpecificWarnings> <DisableSpecificWarnings>4834</DisableSpecificWarnings>
<TreatWarningAsError>true</TreatWarningAsError>
</ClCompile> </ClCompile>
<Link> <Link>
<SubSystem>Console</SubSystem> <SubSystem>Console</SubSystem>
<LanguageStandard>stdcpplatest</LanguageStandard> <LanguageStandard>stdcpplatest</LanguageStandard>
<StringPooling>true</StringPooling> <StringPooling>true</StringPooling>
<FavorSizeOrSpeed>Size</FavorSizeOrSpeed> <FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
<OmitFramePointers />
<OmitFramePointers>true</OmitFramePointers>
<InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>
<BufferSecurityCheck>false</BufferSecurityCheck>
</ClCompile> </ClCompile>
<Link> <Link>
<SubSystem>Console</SubSystem> <SubSystem>Console</SubSystem>
<PreprocessorDefinitions>NDEBUG;_CONSOLE;ASIO_STANDALONE;RESUMEF_ENABLE_MULT_SCHEDULER=1;_SILENCE_CXX17_ALLOCATOR_VOID_DEPRECATION_WARNING=1;ASIO_DISABLE_CONCEPTS=1;%(PreprocessorDefinitions)</PreprocessorDefinitions> <PreprocessorDefinitions>NDEBUG;_CONSOLE;ASIO_STANDALONE;RESUMEF_ENABLE_MULT_SCHEDULER=1;_SILENCE_CXX17_ALLOCATOR_VOID_DEPRECATION_WARNING=1;ASIO_DISABLE_CONCEPTS=1;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>..\librf;..\..\asio\asio\include;..\..\asio-1.10.6\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>..\librf;..\..\asio\asio\include;..\..\asio-1.10.6\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalOptions>/await</AdditionalOptions> <AdditionalOptions>/await</AdditionalOptions>
<ExceptionHandling>Sync</ExceptionHandling>
<FavorSizeOrSpeed>Size</FavorSizeOrSpeed> <FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
<StringPooling>true</StringPooling> <StringPooling>true</StringPooling>
<LanguageStandard>stdcpplatest</LanguageStandard> <LanguageStandard>stdcpplatest</LanguageStandard>
<EnableFiberSafeOptimizations>true</EnableFiberSafeOptimizations> <EnableFiberSafeOptimizations>true</EnableFiberSafeOptimizations>
<BufferSecurityCheck>false</BufferSecurityCheck> <BufferSecurityCheck>false</BufferSecurityCheck>
<EnableParallelCodeGeneration>true</EnableParallelCodeGeneration> <EnableParallelCodeGeneration>true</EnableParallelCodeGeneration>
<TreatWarningAsError>true</TreatWarningAsError>
</ClCompile> </ClCompile>
<Link> <Link>
<SubSystem>Console</SubSystem> <SubSystem>Console</SubSystem>
</Link> </Link>
</ItemDefinitionGroup> </ItemDefinitionGroup>
<ItemGroup> <ItemGroup>
<ClCompile Include="..\benchmark\benchmark_asio_echo.cpp" />
<ClCompile Include="..\benchmark\benchmark_asio_echo.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\benchmark\benchmark_async_mem.cpp" /> <ClCompile Include="..\benchmark\benchmark_async_mem.cpp" />
<ClCompile Include="..\benchmark\benchmark_channel_passing_next.cpp" />
<ClCompile Include="..\benchmark\benchmark_channel_passing_next.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\librf\src\event.cpp" /> <ClCompile Include="..\librf\src\event.cpp" />
<ClCompile Include="..\librf\src\mutex.cpp" /> <ClCompile Include="..\librf\src\mutex.cpp" />
<ClCompile Include="..\librf\src\rf_task.cpp" /> <ClCompile Include="..\librf\src\rf_task.cpp" />

Loading…
Cancel
Save