@@ -275,7 +275,7 @@ private: | |||
{ | |||
auto self = this->shared_from_this(); | |||
asio::async_connect(socket_, endpoint_, | |||
[this, self](std::error_code ec, tcp::resolver::iterator iter) | |||
[this, self](std::error_code ec, tcp::resolver::iterator ) | |||
{ | |||
if (!ec) | |||
{ |
@@ -17,7 +17,7 @@ void resumable_main_benchmark_mem() | |||
for (size_t i = 0; i < N; ++i) | |||
{ | |||
go[=]()->resumef::future_t<size_t> | |||
go[=]()->resumef::generator_t<size_t> | |||
{ | |||
for (size_t k = 0; k < 10; ++k) | |||
{ |
@@ -55,9 +55,10 @@ RESUMEF_NS | |||
using typename awaitable_impl_t<_Ty>::value_type; | |||
using awaitable_impl_t<_Ty>::awaitable_impl_t; | |||
void set_value(value_type value) const | |||
template<class U> | |||
void set_value(U&& value) const | |||
{ | |||
this->_state->set_value(std::move(value)); | |||
this->_state->set_value(std::forward<U>(value)); | |||
this->_state = nullptr; | |||
} | |||
}; |
@@ -1,6 +1,6 @@ | |||
#pragma once | |||
#define LIB_RESUMEF_VERSION 20200 // 2.2.0 | |||
#define LIB_RESUMEF_VERSION 20201 // 2.2.1 | |||
#if defined(RESUMEF_MODULE_EXPORT) | |||
#define RESUMEF_NS export namespace resumef |
@@ -40,3 +40,20 @@ RESUMEF_NS | |||
}; | |||
} | |||
namespace std { | |||
namespace experimental { | |||
/*If the coroutine is defined as task<float> foo(std::string x, bool flag);, | |||
then its Promise type is std::coroutine_traits<task<float>, std::string, bool>::promise_type. | |||
If the coroutine is a non-static member function, such as task<void> my_class::method1(int x) const;, | |||
its Promise type is std::coroutine_traits<task<void>, const my_class&, int>::promise_type. | |||
*/ | |||
template <typename _Ty, typename... Args> | |||
struct coroutine_traits<resumef::future_t<_Ty>, Args...> | |||
{ | |||
typedef resumef::promise_t<_Ty> promise_type; | |||
}; | |||
} | |||
} // namespace std::experimental | |||
@@ -115,22 +115,22 @@ RESUMEF_NS | |||
} | |||
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(const promise_type&) = default; | |||
promise_type& operator = (const promise_type&) = default; | |||
promise_type& get_return_object() | |||
generator_t get_return_object() | |||
{ | |||
return *this; | |||
return generator_t{ *this }; | |||
} | |||
bool initial_suspend() | |||
{ | |||
return (true); | |||
return true; | |||
} | |||
bool final_suspend() | |||
{ | |||
return (true); | |||
return true; | |||
} | |||
void yield_value(_Ty const& _Value) | |||
@@ -138,17 +138,28 @@ RESUMEF_NS | |||
_CurrentValue = std::addressof(_Value); | |||
} | |||
template<class = std::enable_if_t<!std::is_same_v<_Ty, void>, _Ty>> | |||
//template<class = std::enable_if_t<!std::is_same_v<_Ty, void>, _Ty>> | |||
void return_value(_Ty const& _Value) | |||
{ | |||
_CurrentValue = std::addressof(_Value); | |||
} | |||
template<class = std::enable_if_t<std::is_same_v<_Ty, void>, _Ty>> | |||
//template<class = std::enable_if_t<std::is_same_v<_Ty, void>, _Ty>> | |||
void return_value() | |||
{ | |||
_CurrentValue = nullptr; | |||
} | |||
void set_exception(std::exception_ptr e) | |||
{ | |||
std::terminate(); | |||
} | |||
#ifdef __clang__ | |||
void unhandled_exception() | |||
{ | |||
std::terminate(); | |||
} | |||
#endif | |||
template <typename _Uty> | |||
_Uty&& await_transform(_Uty&& _Whatever) | |||
{ | |||
@@ -198,7 +209,6 @@ RESUMEF_NS | |||
*reinterpret_cast<uint32_t*>(_Ptr) = static_cast<uint32_t>(_Size + _State_size); | |||
_Alloc_char _Al; | |||
state_type* st = reinterpret_cast<state_type*>(static_cast<char*>(_Ptr) - _State_size); | |||
st->unlock(); | |||
} | |||
@@ -230,7 +240,6 @@ RESUMEF_NS | |||
generator_t() = default; | |||
generator_t(generator_t const&) = delete; | |||
generator_t& operator=(generator_t const&) = delete; | |||
generator_t(generator_t&& right_) noexcept | |||
@@ -270,3 +279,14 @@ RESUMEF_NS | |||
#pragma pop_macro("new") | |||
#pragma pack(pop) | |||
namespace std { | |||
namespace experimental { | |||
template <typename _Ty, typename _Alloc, typename... Args> | |||
struct coroutine_traits<resumef::generator_t<_Ty, _Alloc>, Args...> | |||
{ | |||
typedef typename resumef::generator_t<_Ty, _Alloc>::promise_type promise_type; | |||
}; | |||
} | |||
} // namespace std::experimental |
@@ -33,7 +33,7 @@ RESUMEF_NS | |||
suspend_on_final final_suspend() noexcept; | |||
void set_exception(std::exception_ptr e); | |||
#ifdef __clang__ | |||
void unhandled_exception(); | |||
void unhandled_exception(); //If the coroutine ends with an uncaught exception, it performs the following: | |||
#endif | |||
future_type get_return_object(); | |||
void cancellation_requested(); | |||
@@ -45,6 +45,11 @@ RESUMEF_NS | |||
assert(_Size >= sizeof(uint32_t) && _Size < (std::numeric_limits<uint32_t>::max)() - sizeof(_State_size)); | |||
_Alloc_char _Al; | |||
/*If allocation fails, the coroutine throws std::bad_alloc, | |||
unless the Promise type defines the member function Promise::get_return_object_on_allocation_failure(). | |||
If that member function is defined, allocation uses the nothrow form of operator new and on allocation failure, | |||
the coroutine immediately returns the object obtained from Promise::get_return_object_on_allocation_failure() to the caller. | |||
*/ | |||
char* ptr = _Al.allocate(_Size + _State_size); | |||
#if RESUMEF_DEBUG_COUNTER | |||
std::cout << " future_promise::new, alloc size=" << (_Size + _State_size) << std::endl; | |||
@@ -67,7 +72,6 @@ RESUMEF_NS | |||
size_t _State_size = _Align_size<state_type>(); | |||
assert(_Size >= sizeof(uint32_t) && _Size < (std::numeric_limits<uint32_t>::max)() - sizeof(_State_size)); | |||
_Alloc_char _Al; | |||
state_type* st = reinterpret_cast<state_type*>(static_cast<char*>(_Ptr) - _State_size); | |||
st->unlock(); | |||
} | |||
@@ -79,8 +83,10 @@ RESUMEF_NS | |||
using typename promise_impl_t<_Ty>::value_type; | |||
using promise_impl_t<_Ty>::get_return_object; | |||
void return_value(value_type val); | |||
void yield_value(value_type val); | |||
template<class U> | |||
void return_value(U&& val); //co_return val | |||
template<class U> | |||
void yield_value(U&& val); | |||
}; | |||
template<> | |||
@@ -88,7 +94,7 @@ RESUMEF_NS | |||
{ | |||
using promise_impl_t<void>::get_return_object; | |||
void return_void(); | |||
void return_void(); //co_return; | |||
void yield_value(); | |||
}; | |||
@@ -1,10 +1,14 @@ | |||
| |||
RESUMEF_NS | |||
{ | |||
/* | |||
Note: the awaiter object is part of coroutine state (as a temporary whose lifetime crosses a suspension point) | |||
and is destroyed before the co_await expression finishes. | |||
It can be used to maintain per-operation state as required by some async I/O APIs without resorting to additional heap allocations. | |||
*/ | |||
struct suspend_on_initial | |||
{ | |||
state_future_t* _state; | |||
inline bool await_ready() noexcept | |||
{ | |||
return false; | |||
@@ -12,17 +16,16 @@ RESUMEF_NS | |||
template<class _PromiseT, typename = std::enable_if_t<is_promise_v<_PromiseT>>> | |||
inline void await_suspend(coroutine_handle<_PromiseT> handler) noexcept | |||
{ | |||
_PromiseT& promise = handler.promise(); | |||
auto* _state = promise.get_state(); | |||
_state->promise_initial_suspend(handler); | |||
} | |||
inline void await_resume() noexcept | |||
{ | |||
_state->promise_await_resume(); | |||
} | |||
}; | |||
struct suspend_on_final | |||
{ | |||
state_future_t* _state; | |||
inline bool await_ready() noexcept | |||
{ | |||
return false; | |||
@@ -30,24 +33,25 @@ RESUMEF_NS | |||
template<class _PromiseT, typename = std::enable_if_t<is_promise_v<_PromiseT>>> | |||
inline void await_suspend(coroutine_handle<_PromiseT> handler) noexcept | |||
{ | |||
_PromiseT& promise = handler.promise(); | |||
auto* _state = promise.get_state(); | |||
_state->promise_final_suspend(handler); | |||
} | |||
inline void await_resume() noexcept | |||
{ | |||
_state->promise_await_resume(); | |||
} | |||
}; | |||
template <typename _Ty> | |||
inline suspend_on_initial promise_impl_t<_Ty>::initial_suspend() noexcept | |||
{ | |||
return { this->get_state() }; | |||
return {}; | |||
} | |||
template <typename _Ty> | |||
inline suspend_on_final promise_impl_t<_Ty>::final_suspend() noexcept | |||
{ | |||
return { this->get_state() }; | |||
return {}; | |||
} | |||
template <typename _Ty> | |||
@@ -60,7 +64,7 @@ RESUMEF_NS | |||
template <typename _Ty> | |||
inline void promise_impl_t<_Ty>::unhandled_exception() | |||
{ | |||
std::terminate(); | |||
this->get_state()->set_exception(std::current_exception()); | |||
} | |||
#endif | |||
@@ -78,15 +82,17 @@ RESUMEF_NS | |||
template<class _Ty> | |||
inline void promise_t<_Ty>::return_value(value_type val) | |||
template<class U> | |||
inline void promise_t<_Ty>::return_value(U&& val) | |||
{ | |||
this->get_state()->set_value(std::move(val)); | |||
this->get_state()->set_value(std::forward<U>(val)); | |||
} | |||
template<class _Ty> | |||
inline void promise_t<_Ty>::yield_value(value_type val) | |||
template<class U> | |||
inline void promise_t<_Ty>::yield_value(U&& val) | |||
{ | |||
this->get_state()->promise_yield_value(this, std::move(val)); | |||
this->get_state()->promise_yield_value(this, std::forward<U>(val)); | |||
} | |||
inline void promise_t<void>::return_void() |
@@ -88,13 +88,14 @@ RESUMEF_NS | |||
{ | |||
std::unique_lock<lock_type> __guard(_mtx); | |||
if (_initor != nullptr && _is_initor) | |||
if (_is_initor == initor_type::Initial) | |||
{ | |||
coroutine_handle<> handler = _initor; | |||
_initor = nullptr; | |||
assert(_initor != nullptr); | |||
_is_initor = initor_type::None; | |||
__guard.unlock(); | |||
handler.resume(); | |||
_initor.resume(); | |||
return; | |||
} | |||
@@ -108,13 +109,12 @@ RESUMEF_NS | |||
return; | |||
} | |||
if (_initor != nullptr && !_is_initor) | |||
if (_is_initor == initor_type::Final) | |||
{ | |||
coroutine_handle<> handler = _initor; | |||
_initor = nullptr; | |||
_is_initor = initor_type::None; | |||
__guard.unlock(); | |||
handler.destroy(); | |||
_initor.destroy(); | |||
return; | |||
} | |||
} | |||
@@ -122,7 +122,7 @@ RESUMEF_NS | |||
bool state_future_t::has_handler() const | |||
{ | |||
scoped_lock<lock_type> __guard(_mtx); | |||
return _coro != nullptr || _initor != nullptr; | |||
return _coro != nullptr || _is_initor != initor_type::None; | |||
} | |||
bool state_future_t::is_ready() const |
@@ -71,6 +71,12 @@ RESUMEF_NS | |||
struct state_future_t : public state_base_t | |||
{ | |||
enum struct initor_type : uint8_t | |||
{ | |||
None, | |||
Initial, | |||
Final | |||
}; | |||
typedef std::recursive_mutex lock_type; | |||
protected: | |||
mutable lock_type _mtx; | |||
@@ -83,7 +89,7 @@ RESUMEF_NS | |||
uint32_t _alloc_size; | |||
bool _has_value = false; | |||
bool _is_awaitor; | |||
bool _is_initor = false; | |||
initor_type _is_initor = initor_type::None; | |||
public: | |||
state_future_t() | |||
{ | |||
@@ -138,7 +144,6 @@ RESUMEF_NS | |||
template<class _PromiseT, typename = std::enable_if_t<is_promise_v<_PromiseT>>> | |||
void promise_initial_suspend(coroutine_handle<_PromiseT> handler); | |||
void promise_await_resume(); | |||
template<class _PromiseT, typename = std::enable_if_t<is_promise_v<_PromiseT>>> | |||
void promise_final_suspend(coroutine_handle<_PromiseT> handler); | |||
}; | |||
@@ -157,28 +162,26 @@ RESUMEF_NS | |||
{ | |||
_alloc_size = sizeof(*this); | |||
} | |||
private: | |||
union union_value_type | |||
{ | |||
value_type _value; | |||
char _[1]; | |||
union_value_type() {} | |||
~union_value_type() {} | |||
}; | |||
union_value_type uv; | |||
~state_t() | |||
{ | |||
if (_has_value) | |||
uv._value.~value_type(); | |||
cast_value_ptr()->~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); | |||
template<class _PromiseT, typename U, typename = std::enable_if_t<is_promise_v<_PromiseT>>> | |||
void promise_yield_value(_PromiseT* promise, U&& val); | |||
template<typename U> | |||
void set_value(U&& val); | |||
private: | |||
value_type * cast_value_ptr() | |||
{ | |||
return static_cast<value_type*>(static_cast<void*>(_value)); | |||
} | |||
void set_value(value_type val); | |||
alignas(value_type) unsigned char _value[sizeof(value_type)]; | |||
}; | |||
template<> |
@@ -4,19 +4,11 @@ RESUMEF_NS | |||
template<class _PromiseT, typename _Enable> | |||
void state_future_t::promise_initial_suspend(coroutine_handle<_PromiseT> handler) | |||
{ | |||
_PromiseT& promise = handler.promise(); | |||
state_base_t* parent_state = promise.get_state(); | |||
(void)parent_state; | |||
assert(this == parent_state); | |||
assert(this->_scheduler == nullptr); | |||
assert(this->_coro == nullptr); | |||
this->_initor = handler; | |||
this->_is_initor = true; | |||
} | |||
inline void state_future_t::promise_await_resume() | |||
{ | |||
this->_initor = handler; | |||
this->_is_initor = initor_type::Initial; | |||
} | |||
template<class _PromiseT, typename _Enable> | |||
@@ -24,13 +16,8 @@ RESUMEF_NS | |||
{ | |||
scoped_lock<lock_type> __guard(this->_mtx); | |||
_PromiseT& promise = handler.promise(); | |||
state_base_t* parent_state = promise.get_state(); | |||
(void)parent_state; | |||
assert(this == parent_state); | |||
this->_initor = handler; | |||
this->_is_initor = false; | |||
this->_is_initor = initor_type::Final; | |||
scheduler_t* sch = this->get_scheduler(); | |||
assert(sch != nullptr); | |||
@@ -77,19 +64,19 @@ RESUMEF_NS | |||
} | |||
template<typename _Ty> | |||
template<class _PromiseT, typename _Enable > | |||
void state_t<_Ty>::promise_yield_value(_PromiseT* promise, _Ty val) | |||
template<class _PromiseT, typename U, typename _Enable > | |||
void state_t<_Ty>::promise_yield_value(_PromiseT* promise, U&& val) | |||
{ | |||
scoped_lock<lock_type> __guard(this->_mtx); | |||
if (this->_has_value) | |||
{ | |||
this->uv._value = std::move(val); | |||
*this->cast_value_ptr() = std::forward<U>(val); | |||
} | |||
else | |||
{ | |||
new (this->cast_value_ptr()) value_type(std::forward<U>(val)); | |||
this->_has_value = true; | |||
new(&this->uv._value) value_type(std::move(val)); | |||
} | |||
coroutine_handle<_PromiseT> handler = coroutine_handle<_PromiseT>::from_promise(*promise); | |||
@@ -112,22 +99,23 @@ RESUMEF_NS | |||
if (!this->_has_value) | |||
std::rethrow_exception(std::make_exception_ptr(future_exception{error_code::not_ready})); | |||
return std::move(this->uv._value); | |||
return std::move(*this->cast_value_ptr()); | |||
} | |||
template<typename _Ty> | |||
void state_t<_Ty>::set_value(value_type val) | |||
template<typename U> | |||
void state_t<_Ty>::set_value(U&& val) | |||
{ | |||
scoped_lock<lock_type> __guard(this->_mtx); | |||
if (this->_has_value) | |||
{ | |||
this->uv._value = std::move(val); | |||
*this->cast_value_ptr() = std::forward<U>(val); | |||
} | |||
else | |||
{ | |||
new (this->cast_value_ptr()) value_type(std::forward<U>(val)); | |||
this->_has_value = true; | |||
new(&this->uv._value) value_type(std::move(val)); | |||
} | |||
scheduler_t* sch = this->get_scheduler(); |
@@ -31,7 +31,7 @@ future_t<> test_channel_read(const channel_t<std::string> & c) | |||
#endif | |||
std::cout << std::endl; | |||
} | |||
catch (channel_exception e) | |||
catch (resumef::channel_exception& e) | |||
{ | |||
//MAX_CHANNEL_QUEUE=0,并且先读后写,会触发read_before_write异常 | |||
std::cout << e.what() << std::endl; |
@@ -33,7 +33,7 @@ future_t<> test_channel_consumer(const channel_t<std::string> & c, size_t cnt) | |||
} | |||
#endif | |||
} | |||
catch (channel_exception e) | |||
catch (channel_exception& e) | |||
{ | |||
//MAX_CHANNEL_QUEUE=0,并且先读后写,会触发read_before_write异常 | |||
scoped_lock<std::mutex> __lock(cout_mutex); |
@@ -71,7 +71,7 @@ void test_wait_any() | |||
go[&]() -> future_t<> | |||
{ | |||
for (int i = 0; i < _countof(evts); ++i) | |||
for (size_t i = 0; i < _countof(evts); ++i) | |||
{ | |||
intptr_t idx = co_await event_t::wait_any(evts); | |||
std::cout << "event " << idx << " signal!" << std::endl; |
@@ -84,7 +84,7 @@ auto tostring_async(_Input_t&& value, _Callable_t&& token) | |||
//适配器类型 | |||
using _Adapter_t = modern_callback_adapter_t<typename resumef::remove_cvref_t<_Callable_t>, void(std::string)>; | |||
//通过适配器获得兼容_Signature_t类型的真正的回调,以及返回值_Return_t | |||
auto adapter = typename _Adapter_t::traits(std::forward<_Callable_t>(token)); | |||
auto adapter = _Adapter_t::traits(std::forward<_Callable_t>(token)); | |||
//callback与token未必是同一个变量,甚至未必是同一个类型 | |||
std::thread([callback = std::move(std::get<0>(adapter)), value = std::forward<_Input_t>(value)] | |||
@@ -101,7 +101,7 @@ auto tostring_async(_Input_t&& value, _Callable_t&& token) | |||
//或者宏版本写法 | |||
#define MODERN_CALLBACK_TRAITS(_Token_value, _Signature_t) \ | |||
using _Adapter_t = modern_callback_adapter_t<typename resumef::remove_cvref_t<_Callable_t>, _Signature_t>; \ | |||
auto _Adapter_value = typename _Adapter_t::traits(std::forward<_Callable_t>(_Token_value)) | |||
auto _Adapter_value = _Adapter_t::traits(std::forward<_Callable_t>(_Token_value)) | |||
#define MODERN_CALLBACK_CALL() std::move(std::get<0>(_Adapter_value)) | |||
#define MODERN_CALLBACK_RETURN() return std::move(std::get<1>(_Adapter_value)).get() | |||
@@ -139,7 +139,7 @@ struct use_future_callback_base_t | |||
auto get_future() const | |||
{ | |||
return _promise.get_future(); | |||
return this->_promise.get_future(); | |||
} | |||
}; | |||
@@ -157,7 +157,7 @@ struct use_future_callback_t<_Promise_traits> : public use_future_callback_base_ | |||
void operator()() const | |||
{ | |||
_promise.set_value(); | |||
this->_promise.set_value(); | |||
} | |||
}; | |||
@@ -170,9 +170,9 @@ struct use_future_callback_t<_Promise_traits, std::exception_ptr> : public use_f | |||
void operator()(std::exception_ptr eptr) const | |||
{ | |||
if (!eptr) | |||
_promise.set_value(); | |||
this->_promise.set_value(); | |||
else | |||
_promise.set_exception(std::move(eptr)); | |||
this->_promise.set_exception(std::move(eptr)); | |||
} | |||
}; | |||
@@ -185,7 +185,7 @@ struct use_future_callback_t<_Promise_traits, _Result_t> : public use_future_cal | |||
template<typename Arg> | |||
void operator()(Arg && arg) const | |||
{ | |||
_promise.set_value(std::forward<Arg>(arg)); | |||
this->_promise.set_value(std::forward<Arg>(arg)); | |||
} | |||
}; | |||
@@ -199,9 +199,9 @@ struct use_future_callback_t<_Promise_traits, std::exception_ptr, _Result_t> : p | |||
void operator()(std::exception_ptr eptr, Arg && arg) const | |||
{ | |||
if (!eptr) | |||
_promise.set_value(std::forward<Arg>(arg)); | |||
this->_promise.set_value(std::forward<Arg>(arg)); | |||
else | |||
_promise.set_exception(std::move(eptr)); | |||
this->_promise.set_exception(std::move(eptr)); | |||
} | |||
}; | |||
@@ -215,7 +215,7 @@ struct use_future_callback_t<_Promise_traits, _Result_t...> : public use_future_ | |||
void operator()(Args&&... args) const | |||
{ | |||
static_assert(sizeof...(Args) == sizeof...(_Result_t), ""); | |||
_promise.set_value(std::make_tuple(std::forward<Args>(args)...)); | |||
this->_promise.set_value(std::make_tuple(std::forward<Args>(args)...)); | |||
} | |||
}; | |||
@@ -230,9 +230,9 @@ struct use_future_callback_t<_Promise_traits, std::exception_ptr, _Result_t...> | |||
{ | |||
static_assert(sizeof...(Args) == sizeof...(_Result_t), ""); | |||
if (!eptr) | |||
_promise.set_value(std::make_tuple(std::forward<Args>(args)...)); | |||
this->_promise.set_value(std::make_tuple(std::forward<Args>(args)...)); | |||
else | |||
_promise.set_exception(std::move(eptr)); | |||
this->_promise.set_exception(std::move(eptr)); | |||
} | |||
}; | |||
@@ -9,7 +9,7 @@ | |||
using namespace resumef; | |||
future_t<> test_loop_sleep(size_t _N, char * ch) | |||
future_t<> test_loop_sleep(size_t _N, const char * ch) | |||
{ | |||
using namespace std::chrono; | |||
@@ -24,7 +24,7 @@ void run_in_thread(channel_t<bool>& c_done) | |||
//循环直到sch_in_thread为nullptr | |||
for (;;) | |||
{ | |||
auto sch = sch_in_thread.load(std::memory_order::acquire); | |||
auto sch = sch_in_thread.load(std::memory_order_acquire); | |||
if (sch == nullptr) | |||
break; | |||
sch->run_one_batch(); | |||
@@ -46,7 +46,7 @@ static void callback_get_long(int64_t val, _Ctype&& cb) | |||
//这种情况下,没有生成 frame-context,因此,并没有promise_type被内嵌在frame-context里 | |||
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) | |||
{ | |||
awaitable.set_value(val); |
@@ -27,7 +27,7 @@ void test_when_any() | |||
co_await sleep_for(1ms * dt); | |||
std::cout << dt << "@a" << std::endl; | |||
return dt; | |||
co_return dt; | |||
}(), | |||
[]() ->future_t<> | |||
{ | |||
@@ -56,7 +56,7 @@ void test_when_any() | |||
co_await sleep_for(1ms * dt); | |||
std::cout << dt << "@" << name << std::endl; | |||
return dt; | |||
co_return dt; | |||
}; | |||
std::vector<future_t<int> > v{ my_sleep("g"), my_sleep("h"), my_sleep("i") }; | |||
@@ -76,7 +76,7 @@ void test_when_all() | |||
co_await sleep_for(1ms * dt); | |||
std::cout << dt << "@" << name << std::endl; | |||
return dt; | |||
co_return dt; | |||
}; | |||
auto my_sleep_v = [](const char * name) -> future_t<> |
@@ -3,7 +3,6 @@ | |||
#include <experimental/resumable> | |||
#include <experimental/generator> | |||
#include <optional> | |||
#include "async_wrapper.hpp" | |||
extern void resumable_main_yield_return(); | |||
extern void resumable_main_timer(); | |||
@@ -34,7 +33,7 @@ int main(int argc, const char* argv[]) | |||
{ | |||
(void)argc; | |||
(void)argv; | |||
resumable_main_switch_scheduler(); | |||
resumable_main_layout(); | |||
//if (argc > 1) | |||
// resumable_main_benchmark_asio_client(atoi(argv[1])); |
@@ -23,6 +23,7 @@ | |||
<ProjectGuid>{C1D4A6BD-592F-4E48-8178-7C87219BF80E}</ProjectGuid> | |||
<Keyword>Win32Proj</Keyword> | |||
<RootNamespace>librf</RootNamespace> | |||
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion> | |||
</PropertyGroup> | |||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> | |||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration"> | |||
@@ -110,7 +111,6 @@ | |||
<CLanguageStandard>c11</CLanguageStandard> | |||
<CppLanguageStandard>c++1y</CppLanguageStandard> | |||
<DisableSpecificWarnings>4834</DisableSpecificWarnings> | |||
<EnableModules>true</EnableModules> | |||
</ClCompile> | |||
<Link> | |||
<SubSystem>Console</SubSystem> |