@@ -3,73 +3,61 @@ | |||
namespace resumef | |||
{ | |||
template<class _Ty> | |||
struct awaitable_t | |||
struct awaitable_impl_t | |||
{ | |||
using value_type = _Ty; | |||
using state_type = state_t<value_type>; | |||
using future_type = future_t<value_type>; | |||
using lock_type = typename state_type::lock_type; | |||
private: | |||
mutable counted_ptr<state_type> _state = make_counted<state_type>(true); | |||
public: | |||
awaitable_t() {} | |||
awaitable_t(const awaitable_t&) = default; | |||
awaitable_t(awaitable_t&&) = default; | |||
awaitable_impl_t() {} | |||
awaitable_impl_t(const awaitable_impl_t&) = default; | |||
awaitable_impl_t(awaitable_impl_t&&) = default; | |||
awaitable_t& operator = (const awaitable_t&) = default; | |||
awaitable_t& operator = (awaitable_t&&) = default; | |||
awaitable_impl_t& operator = (const awaitable_impl_t&) = default; | |||
awaitable_impl_t& operator = (awaitable_impl_t&&) = default; | |||
void set_value(value_type value) const | |||
void set_exception(std::exception_ptr e) const | |||
{ | |||
_state->set_value(std::move(value)); | |||
_state->set_exception(std::move(e)); | |||
_state = nullptr; | |||
} | |||
void set_exception(std::exception_ptr e) | |||
template<class _Exp> | |||
void throw_exception(_Exp e) const | |||
{ | |||
_state->set_exception(std::move(e)); | |||
_state = nullptr; | |||
set_exception(std::make_exception_ptr(std::move(e))); | |||
} | |||
future_type get_future() | |||
{ | |||
return future_type{ _state }; | |||
} | |||
protected: | |||
mutable counted_ptr<state_type> _state = make_counted<state_type>(true); | |||
}; | |||
template<> | |||
struct awaitable_t<void> | |||
template<class _Ty> | |||
struct awaitable_t : public awaitable_impl_t<_Ty> | |||
{ | |||
using value_type = void; | |||
using state_type = state_t<void>; | |||
using future_type = future_t<void>; | |||
using lock_type = typename state_type::lock_type; | |||
mutable counted_ptr<state_type> _state = make_counted<state_type>(true); | |||
using awaitable_impl_t::awaitable_impl_t; | |||
awaitable_t() {} | |||
awaitable_t(const awaitable_t&) = default; | |||
awaitable_t(awaitable_t&&) = default; | |||
awaitable_t& operator = (const awaitable_t&) = default; | |||
awaitable_t& operator = (awaitable_t&&) = default; | |||
void set_value() const | |||
void set_value(value_type value) const | |||
{ | |||
_state->set_value(); | |||
_state->set_value(std::move(value)); | |||
_state = nullptr; | |||
} | |||
}; | |||
void set_exception(std::exception_ptr e) | |||
{ | |||
_state->set_exception(std::move(e)); | |||
_state = nullptr; | |||
} | |||
template<> | |||
struct awaitable_t<void> : public awaitable_impl_t<void> | |||
{ | |||
using awaitable_impl_t::awaitable_impl_t; | |||
future_type get_future() | |||
void set_value() const | |||
{ | |||
return future_type{ _state }; | |||
_state->set_value(); | |||
_state = nullptr; | |||
} | |||
}; | |||
} |
@@ -128,7 +128,8 @@ namespace resumef | |||
template<class _Ty = void> | |||
struct future_t; | |||
using future_vt = future_t<>; | |||
using future_vt [[deprecated]] = future_t<>; | |||
template<class _Ty = void> | |||
struct promise_t; |
@@ -1,20 +1,21 @@ | |||
#include "scheduler.h" | |||
#include "awaitable.h" | |||
#include "sleep.h" | |||
namespace resumef | |||
{ | |||
future_t<> sleep_until_(const std::chrono::system_clock::time_point& tp_, scheduler_t& scheduler_) | |||
{ | |||
promise_vt awaitable; | |||
awaitable_t<> awaitable; | |||
(void)scheduler_.timer()->add(tp_, | |||
[st = awaitable._state](bool cancellation_requested) | |||
[awaitable](bool cancellation_requested) | |||
{ | |||
if (cancellation_requested) | |||
st->throw_exception(timer_canceled_exception{ error_code::timer_canceled }); | |||
awaitable.throw_exception(timer_canceled_exception{ error_code::timer_canceled }); | |||
else | |||
st->set_value(); | |||
awaitable.set_value(); | |||
}); | |||
return awaitable.get_future(); |
@@ -13,8 +13,7 @@ void callback_get_long(int64_t val, _Ctype&& cb) | |||
using namespace std::chrono; | |||
std::thread([val, cb = std::forward<_Ctype>(cb)] | |||
{ | |||
//std::this_thread::sleep_for(500ms); | |||
std::this_thread::sleep_for(2s); | |||
std::this_thread::sleep_for(500ms); | |||
cb(val * val); | |||
}).detach(); | |||
} |
@@ -12,9 +12,9 @@ using namespace resumef; | |||
//请打开结构化异常(/EHa) | |||
auto async_signal_exception(const intptr_t dividend) | |||
{ | |||
promise_t<int64_t> awaitable; | |||
awaitable_t<int64_t> awaitable; | |||
std::thread([dividend, st = awaitable._state] | |||
std::thread([dividend, awaitable] | |||
{ | |||
std::this_thread::sleep_for(std::chrono::milliseconds(50)); | |||
try | |||
@@ -22,11 +22,11 @@ auto async_signal_exception(const intptr_t dividend) | |||
//也可以注释掉这个判断,使用结构化异常。但就获得不了具体描述信息了 | |||
if (dividend == 0) | |||
throw std::logic_error("divided by zero"); | |||
st->set_value(10000 / dividend); | |||
awaitable.set_value(10000 / dividend); | |||
} | |||
catch (...) | |||
{ | |||
st->set_exception(std::current_exception()); | |||
awaitable.set_exception(std::current_exception()); | |||
} | |||
}).detach(); | |||
@@ -35,15 +35,15 @@ auto async_signal_exception(const intptr_t dividend) | |||
auto async_signal_exception2(const intptr_t dividend) | |||
{ | |||
promise_t<int64_t> awaitable; | |||
awaitable_t<int64_t> awaitable; | |||
std::thread([dividend, st = awaitable._state] | |||
std::thread([dividend, awaitable] | |||
{ | |||
std::this_thread::sleep_for(std::chrono::milliseconds(50)); | |||
if (dividend == 0) | |||
st->throw_exception(std::logic_error("divided by zero")); | |||
awaitable.throw_exception(std::logic_error("divided by zero")); | |||
else | |||
st->set_value(10000 / dividend); | |||
awaitable.set_value(10000 / dividend); | |||
}).detach(); | |||
return awaitable.get_future(); |
@@ -26,7 +26,7 @@ auto async_heavy_computing_tasks(int64_t val) | |||
return awaitable.get_future(); | |||
} | |||
future_vt heavy_computing_sequential(int64_t val) | |||
future_t<> heavy_computing_sequential(int64_t val) | |||
{ | |||
for(size_t i = 0; i < 3; ++i) | |||
{ |
@@ -13,7 +13,7 @@ using namespace resumef; | |||
mutex_t g_lock; | |||
std::deque<size_t> g_queue; | |||
future_vt test_mutex_pop(size_t idx) | |||
future_t<> test_mutex_pop(size_t idx) | |||
{ | |||
using namespace std::chrono; | |||
@@ -32,7 +32,7 @@ future_vt test_mutex_pop(size_t idx) | |||
} | |||
} | |||
future_vt test_mutex_push() | |||
future_t<> test_mutex_push() | |||
{ | |||
using namespace std::chrono; | |||
@@ -9,7 +9,7 @@ | |||
using namespace resumef; | |||
future_vt test_routine_use_timer() | |||
future_t<> test_routine_use_timer() | |||
{ | |||
using namespace std::chrono; | |||
std::cout << "test_routine_use_timer" << std::endl; | |||
@@ -22,7 +22,7 @@ future_vt test_routine_use_timer() | |||
} | |||
} | |||
future_vt test_routine_use_timer_2() | |||
future_t<> test_routine_use_timer_2() | |||
{ | |||
std::cout << "test_routine_use_timer_2" << std::endl; | |||
@@ -9,7 +9,7 @@ | |||
using namespace resumef; | |||
future_vt test_sleep_use_timer() | |||
future_t<> test_sleep_use_timer() | |||
{ | |||
using namespace std::chrono; | |||
@@ -37,7 +37,7 @@ void test_wait_all_events_with_signal_by_sleep() | |||
event_t evts[8]; | |||
go[&]() -> future_vt | |||
go[&]() -> future_t<> | |||
{ | |||
if (co_await event_t::wait_all(evts)) | |||
std::cout << "all event signal!" << std::endl; | |||
@@ -48,7 +48,7 @@ void test_wait_all_events_with_signal_by_sleep() | |||
srand((int)time(nullptr)); | |||
for (size_t i = 0; i < _countof(evts); ++i) | |||
{ | |||
go[&, i]() -> future_vt | |||
go[&, i]() -> future_t<> | |||
{ | |||
co_await resumef::sleep_for(1ms * (500 + rand() % 1000)); | |||
evts[i].signal(); |
@@ -9,45 +9,44 @@ | |||
using namespace resumef; | |||
template<size_t _N> | |||
future_vt test_loop_sleep() | |||
future_t<> test_loop_sleep(size_t _N, char * ch) | |||
{ | |||
using namespace std::chrono; | |||
for (size_t i = 0; i < _N; ++i) | |||
{ | |||
co_await resumef::sleep_for(100ms); | |||
std::cout << "."; | |||
std::cout << ch; | |||
} | |||
std::cout << std::endl; | |||
} | |||
future_vt test_recursive_await() | |||
future_t<> test_recursive_await() | |||
{ | |||
std::cout << "---1" << std::endl; | |||
co_await test_loop_sleep<5>(); | |||
std::cout << "A:---1" << std::endl; | |||
co_await test_loop_sleep(5, "="); | |||
std::cout << "---2" << std::endl; | |||
co_await test_loop_sleep<6>(); | |||
std::cout << "A:---2" << std::endl; | |||
co_await test_loop_sleep(6, "="); | |||
std::cout << "---3" << std::endl; | |||
co_await test_loop_sleep<7>(); | |||
std::cout << "A:---3" << std::endl; | |||
co_await test_loop_sleep(7, "="); | |||
std::cout << "---4" << std::endl; | |||
std::cout << "A:---4" << std::endl; | |||
} | |||
future_vt test_recursive_go() | |||
future_t<> test_recursive_go() | |||
{ | |||
std::cout << "---1" << std::endl; | |||
co_await test_loop_sleep<3>(); | |||
std::cout << "B:---1" << std::endl; | |||
co_await test_loop_sleep(3, "+"); | |||
std::cout << "---2" << std::endl; | |||
go test_loop_sleep<5>(); | |||
std::cout << "B:---2" << std::endl; | |||
go test_loop_sleep(8, "*"); | |||
std::cout << "---3" << std::endl; | |||
co_await test_loop_sleep<4>(); | |||
std::cout << "B:---3" << std::endl; | |||
co_await test_loop_sleep(4, "+"); | |||
std::cout << "---4" << std::endl; | |||
std::cout << "B:---4" << std::endl; | |||
} | |||
void resumable_main_suspend_always() |
@@ -29,13 +29,13 @@ void test_when_any() | |||
return dt; | |||
}(), | |||
[]() ->future_vt | |||
[]() ->future_t<> | |||
{ | |||
auto dt = rand() % 1000; | |||
co_await sleep_for(1ms * dt); | |||
std::cout << dt << "@b" << std::endl; | |||
}(), | |||
[]() ->future_vt | |||
[]() ->future_t<> | |||
{ | |||
auto dt = rand() % 1000; | |||
co_await sleep_for(1ms * dt); | |||
@@ -79,7 +79,7 @@ void test_when_all() | |||
return dt; | |||
}; | |||
auto my_sleep_v = [](const char * name) -> future_vt | |||
auto my_sleep_v = [](const char * name) -> future_t<> | |||
{ | |||
auto dt = rand() % 1000; | |||
co_await sleep_for(1ms * dt); |
@@ -29,6 +29,8 @@ extern void resumable_main_benchmark_asio_client(intptr_t nNum); | |||
int main(int argc, const char* argv[]) | |||
{ | |||
resumable_main_cb(); | |||
resumable_main_suspend_always(); | |||
//resumable_main_exception(); | |||
/* | |||
resumable_main_resumable(); | |||
@@ -42,7 +44,6 @@ int main(int argc, const char* argv[]) | |||
resumable_main_multi_thread(); | |||
resumable_main_yield_return(); | |||
resumable_main_timer(); | |||
resumable_main_suspend_always(); | |||
resumable_main_sleep(); | |||
resumable_main_routine(); | |||
resumable_main_resumable(); | |||
@@ -52,7 +53,6 @@ int main(int argc, const char* argv[]) | |||
resumable_main_dynamic_go(); | |||
resumable_main_channel(); | |||
resumable_main_cb(); | |||
resumable_main_exception(); | |||
*/ | |||
return 0; |
@@ -202,10 +202,7 @@ | |||
</ClCompile> | |||
<ClCompile Include="..\librf\src\rf_task.cpp" /> | |||
<ClCompile Include="..\librf\src\scheduler.cpp" /> | |||
<ClCompile Include="..\librf\src\sleep.cpp"> | |||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild> | |||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild> | |||
</ClCompile> | |||
<ClCompile Include="..\librf\src\sleep.cpp" /> | |||
<ClCompile Include="..\librf\src\state.cpp" /> | |||
<ClCompile Include="..\librf\src\timer.cpp" /> | |||
<ClCompile Include="..\librf\src\when.cpp"> | |||
@@ -233,10 +230,7 @@ | |||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild> | |||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild> | |||
</ClCompile> | |||
<ClCompile Include="..\tutorial\test_async_exception.cpp"> | |||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild> | |||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild> | |||
</ClCompile> | |||
<ClCompile Include="..\tutorial\test_async_exception.cpp" /> | |||
<ClCompile Include="..\tutorial\test_async_modern_cb.cpp"> | |||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild> | |||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild> | |||
@@ -259,12 +253,11 @@ | |||
</ClCompile> | |||
<ClCompile Include="..\tutorial\test_async_sleep.cpp"> | |||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild> | |||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild> | |||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild> | |||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild> | |||
</ClCompile> | |||
<ClCompile Include="..\tutorial\test_async_suspend_always.cpp"> | |||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild> | |||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild> | |||
</ClCompile> | |||
<ClCompile Include="..\tutorial\test_async_suspend_always.cpp" /> | |||
<ClCompile Include="..\tutorial\test_async_timer.cpp"> | |||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild> | |||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild> |
@@ -172,7 +172,7 @@ | |||
<Filter>librf\src</Filter> | |||
</ClInclude> | |||
<ClInclude Include="..\librf\src\awaitable.h"> | |||
<Filter>librf</Filter> | |||
<Filter>librf\src</Filter> | |||
</ClInclude> | |||
</ItemGroup> | |||
<ItemGroup> |