@@ -21,3 +21,4 @@ | |||
#include "src/channel.h" | |||
#include "src/scheduler.h" | |||
#include "src/sleep.h" | |||
#include "src/when.h" |
@@ -166,47 +166,47 @@ namespace resumef | |||
} | |||
template<class _Ty2> | |||
awaitable_t<bool> write(_Ty2&& val) const | |||
future_t<bool> write(_Ty2&& val) const | |||
{ | |||
awaitable_t<bool> awaitable; | |||
promise_t<bool> awaitable; | |||
auto awaker = std::make_shared<channel_write_awaker>( | |||
[st = awaitable._state](channel_impl_type * chan) -> bool | |||
{ | |||
st->set_value(chan ? true : false); | |||
return true; | |||
}); | |||
{ | |||
st->set_value(chan ? true : false); | |||
return true; | |||
}); | |||
_chan->write_(std::move(awaker), std::forward<_Ty2>(val)); | |||
return awaitable; | |||
return awaitable.get_future(); | |||
} | |||
awaitable_t<_Ty> read() const | |||
future_t<_Ty> read() const | |||
{ | |||
awaitable_t<_Ty> awaitable; | |||
promise_t<_Ty> awaitable; | |||
auto awaker = std::make_shared<channel_read_awaker>( | |||
[st = awaitable._state](channel_impl_type *, _Ty * val, error_code fe) -> bool | |||
{ | |||
if(val) | |||
st->set_value(std::move(*val)); | |||
else | |||
st->throw_exception(channel_exception{ fe }); | |||
{ | |||
if(val) | |||
st->set_value(std::move(*val)); | |||
else | |||
st->throw_exception(channel_exception{ fe }); | |||
return true; | |||
}); | |||
return true; | |||
}); | |||
_chan->read_(std::move(awaker)); | |||
return awaitable; | |||
return awaitable.get_future(); | |||
} | |||
template<class _Ty2> | |||
awaitable_t<bool> operator << (_Ty2&& val) const | |||
future_t<bool> operator << (_Ty2&& val) const | |||
{ | |||
return std::move(write(std::forward<_Ty2>(val))); | |||
} | |||
awaitable_t<_Ty> operator co_await () const | |||
future_t<_Ty> operator co_await () const | |||
{ | |||
return read(); | |||
} |
@@ -66,9 +66,9 @@ namespace resumef | |||
{ | |||
} | |||
awaitable_t<bool> event_t::wait() const | |||
future_t<bool> event_t::wait() const | |||
{ | |||
awaitable_t<bool> awaitable; | |||
promise_t<bool> awaitable; | |||
auto awaker = std::make_shared<detail::event_awaker>( | |||
[st = awaitable._state](detail::event_impl * e) -> bool | |||
@@ -78,12 +78,12 @@ namespace resumef | |||
}); | |||
_event->wait_(awaker); | |||
return awaitable; | |||
return awaitable.get_future(); | |||
} | |||
awaitable_t<bool> event_t::wait_until_(const clock_type::time_point & tp) const | |||
future_t<bool> event_t::wait_until_(const clock_type::time_point & tp) const | |||
{ | |||
awaitable_t<bool> awaitable; | |||
promise_t<bool> awaitable; | |||
auto awaker = std::make_shared<detail::event_awaker>( | |||
[st = awaitable._state](detail::event_impl * e) -> bool | |||
@@ -99,7 +99,7 @@ namespace resumef | |||
awaker->awake(nullptr, 1); | |||
}); | |||
return awaitable; | |||
return awaitable.get_future(); | |||
} | |||
struct wait_any_awaker | |||
@@ -137,14 +137,14 @@ namespace resumef | |||
} | |||
}; | |||
awaitable_t<intptr_t> event_t::wait_any_(std::vector<event_impl_ptr> && evts) | |||
future_t<intptr_t> event_t::wait_any_(std::vector<event_impl_ptr> && evts) | |||
{ | |||
awaitable_t<intptr_t> awaitable; | |||
promise_t<intptr_t> awaitable; | |||
if (evts.size() <= 0) | |||
{ | |||
awaitable._state->set_value(-1); | |||
return awaitable; | |||
return awaitable.get_future(); | |||
} | |||
auto awaker = std::make_shared<detail::event_awaker>( | |||
@@ -174,12 +174,12 @@ namespace resumef | |||
e->wait_(awaker); | |||
} | |||
return awaitable; | |||
return awaitable.get_future(); | |||
} | |||
awaitable_t<intptr_t> event_t::wait_any_until_(const clock_type::time_point & tp, std::vector<event_impl_ptr> && evts) | |||
future_t<intptr_t> event_t::wait_any_until_(const clock_type::time_point & tp, std::vector<event_impl_ptr> && evts) | |||
{ | |||
awaitable_t<intptr_t> awaitable; | |||
promise_t<intptr_t> awaitable; | |||
auto awaker = std::make_shared<detail::event_awaker>( | |||
[st = awaitable._state, evts](detail::event_impl * e) -> bool | |||
@@ -214,16 +214,16 @@ namespace resumef | |||
awaker->awake(nullptr, 1); | |||
}); | |||
return awaitable; | |||
return awaitable.get_future(); | |||
} | |||
awaitable_t<bool> event_t::wait_all_(std::vector<event_impl_ptr> && evts) | |||
future_t<bool> event_t::wait_all_(std::vector<event_impl_ptr> && evts) | |||
{ | |||
awaitable_t<bool> awaitable; | |||
promise_t<bool> awaitable; | |||
if (evts.size() <= 0) | |||
{ | |||
awaitable._state->set_value(false); | |||
return awaitable; | |||
return awaitable.get_future(); | |||
} | |||
auto awaker = std::make_shared<detail::event_awaker>( | |||
@@ -239,7 +239,7 @@ namespace resumef | |||
e->wait_(awaker); | |||
} | |||
return awaitable; | |||
return awaitable.get_future(); | |||
} | |||
@@ -319,9 +319,9 @@ namespace resumef | |||
//超时后的行为应该表现为: | |||
//要么所有的事件计数减一,要么所有事件计数不动 | |||
//则需要超时后,恢复已经等待的事件计数 | |||
awaitable_t<bool> event_t::wait_all_until_(const clock_type::time_point & tp, std::vector<event_impl_ptr> && evts) | |||
future_t<bool> event_t::wait_all_until_(const clock_type::time_point & tp, std::vector<event_impl_ptr> && evts) | |||
{ | |||
awaitable_t<bool> awaitable; | |||
promise_t<bool> awaitable; | |||
if (evts.size() <= 0) | |||
{ | |||
this_scheduler()->timer()->add_handler(tp, | |||
@@ -329,7 +329,7 @@ namespace resumef | |||
{ | |||
st->set_value(false); | |||
}); | |||
return awaitable; | |||
return awaitable.get_future(); | |||
} | |||
auto ctx = std::make_shared<wait_all_ctx>(); | |||
@@ -353,6 +353,6 @@ namespace resumef | |||
} | |||
return awaitable; | |||
return awaitable.get_future(); | |||
} | |||
} |
@@ -63,16 +63,16 @@ namespace resumef | |||
RF_API awaitable_t<bool> | |||
RF_API future_t<bool> | |||
wait() const; | |||
template<class _Rep, class _Period> | |||
awaitable_t<bool> | |||
future_t<bool> | |||
wait_for(const std::chrono::duration<_Rep, _Period> & dt) const | |||
{ | |||
return wait_for_(std::chrono::duration_cast<clock_type::duration>(dt)); | |||
} | |||
template<class _Clock, class _Duration> | |||
awaitable_t<bool> | |||
future_t<bool> | |||
wait_until(const std::chrono::time_point<_Clock, _Duration> & tp) const | |||
{ | |||
return wait_until_(std::chrono::time_point_cast<clock_type::duration>(tp)); | |||
@@ -83,39 +83,39 @@ namespace resumef | |||
template<class _Iter> | |||
static awaitable_t<intptr_t> | |||
static future_t<intptr_t> | |||
wait_any(_Iter begin_, _Iter end_) | |||
{ | |||
return wait_any_(make_event_vector(begin_, end_)); | |||
} | |||
template<class _Cont> | |||
static awaitable_t<intptr_t> | |||
static future_t<intptr_t> | |||
wait_any(const _Cont & cnt_) | |||
{ | |||
return wait_any_(make_event_vector(std::begin(cnt_), std::end(cnt_))); | |||
} | |||
template<class _Rep, class _Period, class _Iter> | |||
static awaitable_t<intptr_t> | |||
static future_t<intptr_t> | |||
wait_any_for(const std::chrono::duration<_Rep, _Period> & dt, _Iter begin_, _Iter end_) | |||
{ | |||
return wait_any_for_(std::chrono::duration_cast<clock_type::duration>(dt), make_event_vector(begin_, end_)); | |||
} | |||
template<class _Rep, class _Period, class _Cont> | |||
static awaitable_t<intptr_t> | |||
static future_t<intptr_t> | |||
wait_any_for(const std::chrono::duration<_Rep, _Period> & dt, const _Cont & cnt_) | |||
{ | |||
return wait_any_for_(std::chrono::duration_cast<clock_type::duration>(dt), make_event_vector(std::begin(cnt_), std::end(cnt_))); | |||
} | |||
template<class _Clock, class _Duration, class _Iter> | |||
static awaitable_t<intptr_t> | |||
static future_t<intptr_t> | |||
wait_any_until(const std::chrono::time_point<_Clock, _Duration> & tp, _Iter begin_, _Iter end_) | |||
{ | |||
return wait_any_until_(std::chrono::time_point_cast<clock_type::duration>(tp), make_event_vector(begin_, end_)); | |||
} | |||
template<class _Clock, class _Duration, class _Cont> | |||
static awaitable_t<intptr_t> | |||
static future_t<intptr_t> | |||
wait_any_until(const std::chrono::time_point<_Clock, _Duration> & tp, const _Cont & cnt_) | |||
{ | |||
return wait_any_until_(std::chrono::time_point_cast<clock_type::duration>(tp), make_event_vector(std::begin(cnt_), std::end(cnt_))); | |||
@@ -126,39 +126,39 @@ namespace resumef | |||
template<class _Iter> | |||
static awaitable_t<bool> | |||
static future_t<bool> | |||
wait_all(_Iter begin_, _Iter end_) | |||
{ | |||
return wait_all_(make_event_vector(begin_, end_)); | |||
} | |||
template<class _Cont> | |||
static awaitable_t<bool> | |||
static future_t<bool> | |||
wait_all(const _Cont & cnt_) | |||
{ | |||
return wait_all(std::begin(cnt_), std::end(cnt_)); | |||
} | |||
template<class _Rep, class _Period, class _Iter> | |||
static awaitable_t<bool> | |||
static future_t<bool> | |||
wait_all_for(const std::chrono::duration<_Rep, _Period> & dt, _Iter begin_, _Iter end_) | |||
{ | |||
return wait_all_for_(std::chrono::duration_cast<clock_type::duration>(dt), make_event_vector(begin_, end_)); | |||
} | |||
template<class _Rep, class _Period, class _Cont> | |||
static awaitable_t<bool> | |||
static future_t<bool> | |||
wait_all_for(const std::chrono::duration<_Rep, _Period> & dt, const _Cont & cnt_) | |||
{ | |||
return wait_all_for_(std::chrono::duration_cast<clock_type::duration>(dt), make_event_vector(std::begin(cnt_), std::end(cnt_))); | |||
} | |||
template<class _Clock, class _Duration, class _Iter> | |||
static awaitable_t<bool> | |||
static future_t<bool> | |||
wait_all_until(const std::chrono::time_point<_Clock, _Duration> & tp, _Iter begin_, _Iter end_) | |||
{ | |||
return wait_all_until_(std::chrono::time_point_cast<clock_type::duration>(tp), make_event_vector(begin_, end_)); | |||
} | |||
template<class _Clock, class _Duration, class _Cont> | |||
static awaitable_t<bool> | |||
static future_t<bool> | |||
wait_all_until(const std::chrono::time_point<_Clock, _Duration> & tp, const _Cont & cnt_) | |||
{ | |||
return wait_all_until_(std::chrono::time_point_cast<clock_type::duration>(tp), make_event_vector(std::begin(cnt_), std::end(cnt_))); | |||
@@ -166,7 +166,6 @@ namespace resumef | |||
RF_API event_t(const event_t &) = default; | |||
RF_API event_t(event_t &&) = default; | |||
RF_API event_t & operator = (const event_t &) = default; | |||
@@ -184,27 +183,28 @@ namespace resumef | |||
return std::move(evts); | |||
} | |||
inline awaitable_t<bool> wait_for_(const clock_type::duration & dt) const | |||
public: | |||
inline future_t<bool> wait_for_(const clock_type::duration & dt) const | |||
{ | |||
return wait_until_(clock_type::now() + dt); | |||
} | |||
RF_API awaitable_t<bool> wait_until_(const clock_type::time_point & tp) const; | |||
RF_API future_t<bool> wait_until_(const clock_type::time_point & tp) const; | |||
RF_API static awaitable_t<intptr_t> wait_any_(std::vector<event_impl_ptr> && evts); | |||
inline static awaitable_t<intptr_t> wait_any_for_(const clock_type::duration & dt, std::vector<event_impl_ptr> && evts) | |||
RF_API static future_t<intptr_t> wait_any_(std::vector<event_impl_ptr> && evts); | |||
inline static future_t<intptr_t> wait_any_for_(const clock_type::duration & dt, std::vector<event_impl_ptr> && evts) | |||
{ | |||
return wait_any_until_(clock_type::now() + dt, std::forward<std::vector<event_impl_ptr>>(evts)); | |||
} | |||
RF_API static awaitable_t<intptr_t> wait_any_until_(const clock_type::time_point & tp, std::vector<event_impl_ptr> && evts); | |||
RF_API static future_t<intptr_t> wait_any_until_(const clock_type::time_point & tp, std::vector<event_impl_ptr> && evts); | |||
RF_API static awaitable_t<bool> wait_all_(std::vector<event_impl_ptr> && evts); | |||
inline static awaitable_t<bool> wait_all_for_(const clock_type::duration & dt, std::vector<event_impl_ptr> && evts) | |||
RF_API static future_t<bool> wait_all_(std::vector<event_impl_ptr> && evts); | |||
inline static future_t<bool> wait_all_for_(const clock_type::duration & dt, std::vector<event_impl_ptr> && evts) | |||
{ | |||
return wait_all_until_(clock_type::now() + dt, std::forward<std::vector<event_impl_ptr>>(evts)); | |||
} | |||
RF_API static awaitable_t<bool> wait_all_until_(const clock_type::time_point & tp, std::vector<event_impl_ptr> && evts); | |||
RF_API static future_t<bool> wait_all_until_(const clock_type::time_point & tp, std::vector<event_impl_ptr> && evts); | |||
}; | |||
} |
@@ -20,8 +20,8 @@ namespace resumef | |||
future_impl_t() = default; | |||
future_impl_t(future_impl_t&& f) = default; | |||
future_impl_t & operator = (future_impl_t&& f) = default; | |||
future_impl_t(const future_impl_t&) = delete; | |||
future_impl_t & operator = (const future_impl_t&) = delete; | |||
future_impl_t(const future_impl_t&) = default; | |||
future_impl_t & operator = (const future_impl_t&) = default; | |||
//------------------------------------------------------------------------------------------ | |||
//以下是与编译器生成的resumable function交互的接口 | |||
@@ -78,11 +78,11 @@ namespace resumef | |||
} | |||
// movable, but not copyable | |||
future_t(const future_t&) = delete; | |||
future_t(const future_t&) = default; | |||
future_t(future_t&& f) = default; | |||
future_t() = default; | |||
future_t & operator = (const future_t&) = delete; | |||
future_t & operator = (const future_t&) = default; | |||
future_t & operator = (future_t&& f) = default; | |||
//------------------------------------------------------------------------------------------ | |||
@@ -290,6 +290,7 @@ namespace resumef | |||
using promise_vt = promise_t<void>; | |||
/* | |||
template <typename T = void> | |||
struct awaitable_t | |||
{ | |||
@@ -331,6 +332,7 @@ namespace resumef | |||
}; | |||
using awaitable_vt = awaitable_t<void>; | |||
*/ | |||
#if RESUMEF_ENABLE_MULT_SCHEDULER | |||
inline promise_t<void> * state_base::parent_promise() const |
@@ -78,9 +78,9 @@ namespace resumef | |||
{ | |||
} | |||
awaitable_t<bool> mutex_t::lock() const | |||
future_t<bool> mutex_t::lock() const | |||
{ | |||
awaitable_t<bool> awaitable; | |||
promise_t<bool> awaitable; | |||
auto awaker = std::make_shared<detail::mutex_awaker>( | |||
[st = awaitable._state](detail::mutex_impl * e) -> bool | |||
@@ -90,7 +90,7 @@ namespace resumef | |||
}); | |||
_locker->lock_(awaker); | |||
return awaitable; | |||
return awaitable.get_future(); | |||
} | |||
bool mutex_t::try_lock() const | |||
@@ -103,9 +103,9 @@ namespace resumef | |||
return _locker->try_lock_(dummy_awaker); | |||
} | |||
awaitable_t<bool> mutex_t::try_lock_until_(const clock_type::time_point & tp) const | |||
future_t<bool> mutex_t::try_lock_until_(const clock_type::time_point & tp) const | |||
{ | |||
awaitable_t<bool> awaitable; | |||
promise_t<bool> awaitable; | |||
auto awaker = std::make_shared<detail::mutex_awaker>( | |||
[st = awaitable._state](detail::mutex_impl * e) -> bool | |||
@@ -121,6 +121,6 @@ namespace resumef | |||
awaker->awake(nullptr, 1); | |||
}); | |||
return awaitable; | |||
return awaitable.get_future(); | |||
} | |||
} |
@@ -57,7 +57,7 @@ namespace resumef | |||
} | |||
RF_API awaitable_t<bool> | |||
RF_API future_t<bool> | |||
lock() const; | |||
RF_API bool | |||
try_lock() const; | |||
@@ -83,13 +83,13 @@ namespace resumef | |||
RF_API mutex_t & operator = (const mutex_t &) = default; | |||
RF_API mutex_t & operator = (mutex_t &&) = default; | |||
private: | |||
inline awaitable_t<bool> try_lock_for_(const clock_type::duration & dt) const | |||
inline future_t<bool> try_lock_for_(const clock_type::duration & dt) const | |||
{ | |||
return try_lock_until_(clock_type::now() + dt); | |||
} | |||
RF_API awaitable_t<bool> try_lock_until_(const clock_type::time_point & tp) const; | |||
RF_API future_t<bool> try_lock_until_(const clock_type::time_point & tp) const; | |||
}; | |||
#define resumf_guard_lock(lker) (lker).lock(); resumef::scoped_lock<resumef::mutex_t> __resumf_guard##lker##__((lker), std::adopt_lock) | |||
#define resumf_guard_lock(lker) (lker).lock(); resumef::scoped_lock<resumef::mutex_t> __resumf_guard##lker##__(std::adopt_lock, (lker)) | |||
} |
@@ -5,9 +5,9 @@ | |||
namespace resumef | |||
{ | |||
awaitable_t<bool> sleep_until_(const std::chrono::system_clock::time_point& tp_, scheduler & scheduler_) | |||
future_t<bool> sleep_until_(const std::chrono::system_clock::time_point& tp_, scheduler & scheduler_) | |||
{ | |||
resumef::awaitable_t<bool> awaitable; | |||
promise_t<bool> awaitable; | |||
scheduler_.timer()->add(tp_, | |||
[st = awaitable._state](bool cancellation_requested) | |||
@@ -15,6 +15,6 @@ namespace resumef | |||
st->set_value(cancellation_requested); | |||
}); | |||
return awaitable; | |||
return awaitable.get_future(); | |||
} | |||
} |
@@ -4,31 +4,31 @@ namespace resumef | |||
{ | |||
struct scheduler; | |||
RF_API awaitable_t<bool> sleep_until_(const std::chrono::system_clock::time_point& tp_, scheduler & scheduler_); | |||
RF_API future_t<bool> sleep_until_(const std::chrono::system_clock::time_point& tp_, scheduler & scheduler_); | |||
inline awaitable_t<bool> sleep_for_(const std::chrono::system_clock::duration& dt_, scheduler & scheduler_) | |||
inline future_t<bool> sleep_for_(const std::chrono::system_clock::duration& dt_, scheduler & scheduler_) | |||
{ | |||
return std::move(sleep_until_(std::chrono::system_clock::now() + dt_, scheduler_)); | |||
} | |||
template<class _Rep, class _Period> | |||
awaitable_t<bool> sleep_for(const std::chrono::duration<_Rep, _Period>& dt_, scheduler & scheduler_) | |||
future_t<bool> sleep_for(const std::chrono::duration<_Rep, _Period>& dt_, scheduler & scheduler_) | |||
{ | |||
return std::move(sleep_for_(std::chrono::duration_cast<std::chrono::system_clock::duration>(dt_), scheduler_)); | |||
} | |||
template<class _Rep, class _Period> | |||
awaitable_t<bool> sleep_for(const std::chrono::duration<_Rep, _Period>& dt_) | |||
future_t<bool> sleep_for(const std::chrono::duration<_Rep, _Period>& dt_) | |||
{ | |||
return std::move(sleep_for_(std::chrono::duration_cast<std::chrono::system_clock::duration>(dt_), *this_scheduler())); | |||
} | |||
template<class _Clock, class _Duration = typename _Clock::duration> | |||
awaitable_t<bool> sleep_until(const std::chrono::time_point<_Clock, _Duration>& tp_, scheduler & scheduler_) | |||
future_t<bool> sleep_until(const std::chrono::time_point<_Clock, _Duration>& tp_, scheduler & scheduler_) | |||
{ | |||
return std::move(sleep_until_(std::chrono::time_point_cast<std::chrono::system_clock::duration>(tp_), scheduler_)); | |||
} | |||
template<class _Clock, class _Duration> | |||
awaitable_t<bool> sleep_until(const std::chrono::time_point<_Clock, _Duration>& tp_) | |||
future_t<bool> sleep_until(const std::chrono::time_point<_Clock, _Duration>& tp_) | |||
{ | |||
return std::move(sleep_until_(std::chrono::time_point_cast<std::chrono::system_clock::duration>(tp_), *this_scheduler())); | |||
} |
@@ -0,0 +1,53 @@ | |||
#include "when.h" | |||
#include <assert.h> | |||
#include "scheduler.h" | |||
#pragma once | |||
#include "_awaker.h" | |||
namespace resumef | |||
{ | |||
namespace detail | |||
{ | |||
when_impl::when_impl(intptr_t initial_counter_) | |||
: _counter(initial_counter_) | |||
{ | |||
} | |||
void when_impl::signal() | |||
{ | |||
scoped_lock<lock_type> lock_(this->_lock); | |||
if (--this->_counter == 0) | |||
{ | |||
_awakes->awake(this, 1); | |||
} | |||
} | |||
void when_impl::reset(intptr_t initial_counter_) | |||
{ | |||
scoped_lock<lock_type> lock_(this->_lock); | |||
this->_awakes = nullptr; | |||
this->_counter = initial_counter_; | |||
} | |||
bool when_impl::wait_(const when_awaker_ptr & awaker) | |||
{ | |||
assert(awaker); | |||
scoped_lock<lock_type> lock_(this->_lock); | |||
if (this->_counter == 0) | |||
{ | |||
awaker->awake(this, 1); | |||
return true; | |||
} | |||
else | |||
{ | |||
this->_awakes = awaker; | |||
return false; | |||
} | |||
} | |||
} | |||
} |
@@ -0,0 +1,122 @@ | |||
#pragma once | |||
#include "_awaker.h" | |||
namespace resumef | |||
{ | |||
namespace detail | |||
{ | |||
struct when_impl; | |||
typedef _awaker<when_impl> when_awaker; | |||
typedef std::shared_ptr<when_awaker> when_awaker_ptr; | |||
struct when_impl : public std::enable_shared_from_this<when_impl> | |||
{ | |||
private: | |||
//typedef spinlock lock_type; | |||
typedef std::recursive_mutex lock_type; | |||
when_awaker_ptr _awakes; | |||
intptr_t _counter; | |||
lock_type _lock; | |||
public: | |||
RF_API when_impl(intptr_t initial_counter_); | |||
RF_API void signal(); | |||
RF_API void reset(intptr_t initial_counter_); | |||
//如果已经触发了awaker,则返回true | |||
RF_API bool wait_(const when_awaker_ptr & awaker); | |||
template<class callee_t, class dummy_t = std::enable_if<!std::is_same<std::remove_cv_t<callee_t>, event_awaker_ptr>::value>> | |||
auto wait(callee_t && awaker, dummy_t * dummy_ = nullptr) | |||
{ | |||
return wait_(std::make_shared<event_awaker>(std::forward<callee_t>(awaker))); | |||
} | |||
when_impl(const when_impl &) = delete; | |||
when_impl(when_impl &&) = delete; | |||
when_impl & operator = (const when_impl &) = delete; | |||
when_impl & operator = (when_impl &&) = delete; | |||
}; | |||
typedef std::shared_ptr<when_impl> when_impl_ptr; | |||
template<class _Fty> | |||
struct when_one_functor | |||
{ | |||
when_impl_ptr _e; | |||
mutable future_t<_Fty> _f; | |||
when_one_functor(const detail::when_impl_ptr & e, future_t<_Fty> f) | |||
:_e(e) | |||
, _f(std::move(f)) | |||
{} | |||
when_one_functor(when_one_functor &&) = default; | |||
inline future_vt operator ()() const | |||
{ | |||
co_await _f; | |||
_e->signal(); | |||
} | |||
}; | |||
inline void when_one__(scheduler * s, const detail::when_impl_ptr & e) | |||
{ | |||
} | |||
template<class _Fty, class... _Rest> | |||
inline void when_one__(scheduler * s, const detail::when_impl_ptr & e, future_t<_Fty> f, _Rest&&... rest) | |||
{ | |||
(*s) + when_one_functor<_Fty>{e, std::move(f)}; | |||
when_one__(s, e, std::forward<_Rest>(rest)...); | |||
} | |||
} | |||
template<class... _Fty> | |||
future_t<bool> when_count(size_t counter, scheduler * s, _Fty&&... f) | |||
{ | |||
promise_t<bool> awaitable; | |||
detail::when_impl_ptr _event = std::make_shared<detail::when_impl>(counter); | |||
auto awaker = std::make_shared<detail::when_awaker>( | |||
[st = awaitable._state](detail::when_impl * e) -> bool | |||
{ | |||
st->set_value(e ? true : false); | |||
return true; | |||
}); | |||
_event->wait_(awaker); | |||
detail::when_one__(s, _event, std::forward<_Fty>(f)...); | |||
return awaitable.get_future(); | |||
} | |||
template<class... _Fty> | |||
future_t<bool> when_all(scheduler * s, _Fty&&... f) | |||
{ | |||
return when_count(sizeof...(_Fty), s, std::forward<_Fty>(f)...); | |||
} | |||
template<class... _Fty> | |||
future_t<bool> when_all(_Fty&&... f) | |||
{ | |||
return when_count(sizeof...(_Fty), this_scheduler(), std::forward<_Fty>(f)...); | |||
} | |||
template<class... _Fty> | |||
future_t<bool> when_any(scheduler * s, _Fty&&... f) | |||
{ | |||
static_assert(sizeof...(_Fty) > 0); | |||
return when_count(1, s, std::forward<_Fty>(f)...); | |||
} | |||
template<class... _Fty> | |||
future_t<bool> when_any(_Fty&&... f) | |||
{ | |||
static_assert(sizeof...(_Fty) > 0); | |||
return when_count(1, this_scheduler(), std::forward<_Fty>(f)...); | |||
} | |||
} |
@@ -12,7 +12,7 @@ using namespace resumef; | |||
//请打开结构化异常(/EHa) | |||
auto async_signal_exception(const intptr_t dividend) | |||
{ | |||
awaitable_t<int64_t> awaitable; | |||
promise_t<int64_t> awaitable; | |||
std::thread([dividend, st = awaitable._state] | |||
{ | |||
@@ -30,12 +30,12 @@ auto async_signal_exception(const intptr_t dividend) | |||
} | |||
}).detach(); | |||
return awaitable; | |||
return awaitable.get_future(); | |||
} | |||
auto async_signal_exception2(const intptr_t dividend) | |||
{ | |||
awaitable_t<int64_t> awaitable; | |||
promise_t<int64_t> awaitable; | |||
std::thread([dividend, st = awaitable._state] | |||
{ | |||
@@ -46,7 +46,7 @@ auto async_signal_exception2(const intptr_t dividend) | |||
st->set_value(10000 / dividend); | |||
}).detach(); | |||
return awaitable; | |||
return awaitable.get_future(); | |||
} | |||
future_vt test_signal_exception() |
@@ -15,7 +15,7 @@ auto async_heavy_computing_tasks(int64_t val) | |||
{ | |||
using namespace std::chrono; | |||
awaitable_t<int64_t> awaitable; | |||
promise_t<int64_t> awaitable; | |||
std::thread([val, st = awaitable._state] | |||
{ | |||
@@ -23,7 +23,7 @@ auto async_heavy_computing_tasks(int64_t val) | |||
st->set_value(val * val); | |||
}).detach(); | |||
return awaitable; | |||
return awaitable.get_future(); | |||
} | |||
future_vt heavy_computing_sequential(int64_t val) |
@@ -0,0 +1,74 @@ | |||
| |||
#include <chrono> | |||
#include <iostream> | |||
#include <string> | |||
#include <conio.h> | |||
#include <thread> | |||
#include <experimental/resumable> | |||
#include "librf.h" | |||
using namespace resumef; | |||
void test_when_any() | |||
{ | |||
using namespace std::chrono; | |||
GO | |||
{ | |||
co_await when_any( | |||
[]() ->future_vt | |||
{ | |||
auto dt = rand() % 1000; | |||
co_await sleep_for(1ms * dt); | |||
std::cout << dt << "@1000" << std::endl; | |||
}(), | |||
[]() ->future_vt | |||
{ | |||
auto dt = rand() % 2000; | |||
co_await sleep_for(1ms * dt); | |||
std::cout << dt << "@2000" << std::endl; | |||
}(), | |||
[]() ->future_vt | |||
{ | |||
auto dt = rand() % 3000; | |||
co_await sleep_for(1ms * dt); | |||
std::cout << dt << "@3000" << std::endl; | |||
}()); | |||
std::cout << "any done!" << std::endl; | |||
}; | |||
this_scheduler()->run_until_notask(); | |||
} | |||
void test_when_all() | |||
{ | |||
using namespace std::chrono; | |||
auto my_sleep = [](const char * name) -> future_vt | |||
{ | |||
auto dt = rand() % 1000; | |||
co_await sleep_for(1ms * dt); | |||
std::cout << dt << "@" << name << std::endl; | |||
}; | |||
GO | |||
{ | |||
co_await when_all(); | |||
std::cout << "zero!" << std::endl; | |||
co_await when_all(my_sleep("a"), my_sleep("b")); | |||
co_await my_sleep("c"); | |||
co_await when_all(my_sleep("d"), my_sleep("e"), my_sleep("f")); | |||
std::cout << "all done!" << std::endl; | |||
}; | |||
this_scheduler()->run_until_notask(); | |||
} | |||
void resumable_main_when_all() | |||
{ | |||
srand((uint32_t)time(nullptr)); | |||
test_when_any(); | |||
std::cout << std::endl; | |||
test_when_all(); | |||
} |
@@ -16,12 +16,13 @@ extern void resumable_main_channel(); | |||
extern void resumable_main_cb(); | |||
extern void resumable_main_multi_thread(); | |||
extern void resumable_main_channel_mult_thread(); | |||
extern void resumable_main_when_all(); | |||
extern void resumable_main_benchmark_mem(); | |||
int main(int argc, const char * argv[]) | |||
{ | |||
resumable_main_channel_mult_thread(); | |||
resumable_main_when_all(); | |||
//resumable_main_multi_thread(); | |||
return 0; | |||
@@ -90,6 +90,7 @@ | |||
<SDLCheck>true</SDLCheck> | |||
<AdditionalIncludeDirectories>..\librf;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> | |||
<AdditionalOptions>/await /std:c++latest </AdditionalOptions> | |||
<MultiProcessorCompilation>true</MultiProcessorCompilation> | |||
</ClCompile> | |||
<Link> | |||
<SubSystem>Console</SubSystem> | |||
@@ -104,6 +105,7 @@ | |||
<SDLCheck>true</SDLCheck> | |||
<AdditionalIncludeDirectories>..\librf;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> | |||
<AdditionalOptions>/await /std:c++latest </AdditionalOptions> | |||
<MultiProcessorCompilation>true</MultiProcessorCompilation> | |||
</ClCompile> | |||
<Link> | |||
<SubSystem>Console</SubSystem> | |||
@@ -120,6 +122,7 @@ | |||
<SDLCheck>true</SDLCheck> | |||
<AdditionalIncludeDirectories>..\librf;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> | |||
<AdditionalOptions>/await /std:c++latest </AdditionalOptions> | |||
<MultiProcessorCompilation>true</MultiProcessorCompilation> | |||
</ClCompile> | |||
<Link> | |||
<SubSystem>Console</SubSystem> | |||
@@ -146,6 +149,7 @@ | |||
<StringPooling>true</StringPooling> | |||
<LanguageStandard>stdcpplatest</LanguageStandard> | |||
<BufferSecurityCheck>false</BufferSecurityCheck> | |||
<MultiProcessorCompilation>true</MultiProcessorCompilation> | |||
</ClCompile> | |||
<Link> | |||
<SubSystem>Console</SubSystem> | |||
@@ -165,6 +169,7 @@ | |||
<ClCompile Include="..\librf\src\sleep.cpp" /> | |||
<ClCompile Include="..\librf\src\state.cpp" /> | |||
<ClCompile Include="..\librf\src\timer.cpp" /> | |||
<ClCompile Include="..\librf\src\when.cpp" /> | |||
<ClCompile Include="..\tutorial\test_async_cb.cpp" /> | |||
<ClCompile Include="..\tutorial\test_async_channel.cpp" /> | |||
<ClCompile Include="..\tutorial\test_async_channel_mult_thread.cpp" /> | |||
@@ -179,6 +184,7 @@ | |||
<ClCompile Include="..\tutorial\test_async_sleep.cpp" /> | |||
<ClCompile Include="..\tutorial\test_async_suspend_always.cpp" /> | |||
<ClCompile Include="..\tutorial\test_async_timer.cpp" /> | |||
<ClCompile Include="..\tutorial\test_async_when_all.cpp" /> | |||
<ClCompile Include="..\tutorial\test_async_yield_return.cpp" /> | |||
<ClCompile Include="librf.cpp" /> | |||
</ItemGroup> | |||
@@ -200,6 +206,7 @@ | |||
<ClInclude Include="..\librf\src\timer.h" /> | |||
<ClInclude Include="..\librf\src\unix\coroutine.h" /> | |||
<ClInclude Include="..\librf\src\utils.h" /> | |||
<ClInclude Include="..\librf\src\when.h" /> | |||
<ClInclude Include="..\librf\src\_awaker.h" /> | |||
</ItemGroup> | |||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> |
@@ -94,6 +94,12 @@ | |||
<ClCompile Include="..\tutorial\test_async_channel_mult_thread.cpp"> | |||
<Filter>tutorial</Filter> | |||
</ClCompile> | |||
<ClCompile Include="..\tutorial\test_async_when_all.cpp"> | |||
<Filter>tutorial</Filter> | |||
</ClCompile> | |||
<ClCompile Include="..\librf\src\when.cpp"> | |||
<Filter>librf\src</Filter> | |||
</ClCompile> | |||
</ItemGroup> | |||
<ItemGroup> | |||
<ClInclude Include="..\librf\librf.h"> | |||
@@ -150,5 +156,8 @@ | |||
<ClInclude Include="..\librf\src\counted_ptr.h"> | |||
<Filter>librf\src</Filter> | |||
</ClInclude> | |||
<ClInclude Include="..\librf\src\when.h"> | |||
<Filter>librf\src</Filter> | |||
</ClInclude> | |||
</ItemGroup> | |||
</Project> |