#include <thread> | #include <thread> | ||||
*/ | */ | ||||
#include <asio.hpp> | |||||
#include "librf.h" | #include "librf.h" | ||||
#include <asio.hpp> | |||||
#include "src/asio_task.h" | #include "src/asio_task.h" | ||||
#pragma warning(disable : 4834) | #pragma warning(disable : 4834) | ||||
std::array<char, BUF_SIZE> buffer; | std::array<char, BUF_SIZE> buffer; | ||||
for(;;) | for(;;) | ||||
{ | { | ||||
#ifndef __clang__ | |||||
try | try | ||||
#endif | |||||
{ | { | ||||
bytes_transferred += co_await socket.async_read_some(asio::buffer(buffer.data() + bytes_transferred, buffer.size() - bytes_transferred), rf_task); | bytes_transferred += co_await socket.async_read_some(asio::buffer(buffer.data() + bytes_transferred, buffer.size() - bytes_transferred), rf_task); | ||||
if (bytes_transferred >= buffer.size()) | if (bytes_transferred >= buffer.size()) | ||||
g_echo_count.fetch_add(1, std::memory_order_release); | g_echo_count.fetch_add(1, std::memory_order_release); | ||||
} | } | ||||
} | } | ||||
#ifndef __clang__ | |||||
catch (std::exception & e) | catch (std::exception & e) | ||||
{ | { | ||||
std::cerr << e.what() << std::endl; | std::cerr << e.what() << std::endl; | ||||
break; | break; | ||||
} | } | ||||
#endif | |||||
} | } | ||||
} | } | ||||
{ | { | ||||
for (;;) | for (;;) | ||||
{ | { | ||||
#ifndef __clang__ | |||||
try | try | ||||
#endif | |||||
{ | { | ||||
co_await acceptor.async_accept(socketes.c[idx], rf_task); | co_await acceptor.async_accept(socketes.c[idx], rf_task); | ||||
go RunEchoSession(std::move(socketes.c[idx])); | go RunEchoSession(std::move(socketes.c[idx])); | ||||
} | } | ||||
#ifndef __clang__ | |||||
catch (std::exception & e) | catch (std::exception & e) | ||||
{ | { | ||||
std::cerr << e.what() << std::endl; | std::cerr << e.what() << std::endl; | ||||
} | } | ||||
#endif | |||||
} | } | ||||
}; | }; | ||||
} | } | ||||
{ | { | ||||
std::shared_ptr<tcp::socket> sptr = std::make_shared<tcp::socket>(ios); | std::shared_ptr<tcp::socket> sptr = std::make_shared<tcp::socket>(ios); | ||||
#ifndef __clang__ | |||||
try | try | ||||
#endif | |||||
{ | { | ||||
co_await asio::async_connect(*sptr, ep, rf_task); | co_await asio::async_connect(*sptr, ep, rf_task); | ||||
for (auto & c : write_buff_) | for (auto & c : write_buff_) | ||||
c = 'A' + rand() % 52; | c = 'A' + rand() % 52; | ||||
#ifndef __clang__ | |||||
try | try | ||||
#endif | |||||
{ | { | ||||
for (;;) | for (;;) | ||||
{ | { | ||||
co_await asio::async_write(*sptr, asio::buffer(write_buff_), rf_task); | co_await asio::async_write(*sptr, asio::buffer(write_buff_), rf_task); | ||||
} | } | ||||
} | } | ||||
#ifndef __clang__ | |||||
catch (std::exception & e) | catch (std::exception & e) | ||||
{ | { | ||||
std::cerr << e.what() << std::endl; | std::cerr << e.what() << std::endl; | ||||
} | } | ||||
#endif | |||||
}; | }; | ||||
GO | GO | ||||
{ | { | ||||
#ifndef __clang__ | |||||
try | try | ||||
#endif | |||||
{ | { | ||||
std::array<char, BUF_SIZE> read_buff_; | std::array<char, BUF_SIZE> read_buff_; | ||||
for (;;) | for (;;) | ||||
co_await sptr->async_read_some(asio::buffer(read_buff_), rf_task); | co_await sptr->async_read_some(asio::buffer(read_buff_), rf_task); | ||||
} | } | ||||
} | } | ||||
#ifndef __clang__ | |||||
catch (std::exception & e) | catch (std::exception & e) | ||||
{ | { | ||||
std::cerr << e.what() << std::endl; | std::cerr << e.what() << std::endl; | ||||
} | } | ||||
#endif | |||||
}; | }; | ||||
} | } | ||||
#ifndef __clang__ | |||||
catch (std::exception & e) | catch (std::exception & e) | ||||
{ | { | ||||
std::cerr << e.what() << std::endl; | std::cerr << e.what() << std::endl; | ||||
} | } | ||||
#endif | |||||
} | } | ||||
#if _HAS_CXX17 | #if _HAS_CXX17 | ||||
std::array<char, BUF_SIZE> read_buff_; | std::array<char, BUF_SIZE> read_buff_; | ||||
std::array<char, BUF_SIZE> write_buff_; | std::array<char, BUF_SIZE> write_buff_; | ||||
#ifndef __clang__ | |||||
try | try | ||||
#endif | |||||
{ | { | ||||
co_await asio::async_connect(socket_, ep, rf_task); | co_await asio::async_connect(socket_, ep, rf_task); | ||||
); | ); | ||||
} | } | ||||
} | } | ||||
#ifndef __clang__ | |||||
catch (std::exception & e) | catch (std::exception & e) | ||||
{ | { | ||||
std::cerr << e.what() << std::endl; | std::cerr << e.what() << std::endl; | ||||
} | } | ||||
#endif | |||||
} | } | ||||
void resumable_main_benchmark_asio_client_with_rf(intptr_t nNum) | void resumable_main_benchmark_asio_client_with_rf(intptr_t nNum) |
#include "librf.h" | #include "librf.h" | ||||
const size_t N = 1000000; | const size_t N = 1000000; | ||||
const size_t LOOP_COUNT = 100; | |||||
volatile size_t globalValue = 0; | volatile size_t globalValue = 0; | ||||
{ | { | ||||
go[=]()->resumef::generator_t<size_t> | go[=]()->resumef::generator_t<size_t> | ||||
{ | { | ||||
for (size_t k = 0; k < 10; ++k) | |||||
for (size_t k = 0; k < LOOP_COUNT; ++k) | |||||
{ | { | ||||
globalValue += i * k; | globalValue += i * k; | ||||
co_yield k; | co_yield k; | ||||
} | } | ||||
resumef::this_scheduler()->run_until_notask(); | resumef::this_scheduler()->run_until_notask(); | ||||
std::cout << "press any key to continue." << std::endl; | |||||
(void)_getch(); | (void)_getch(); | ||||
} | } |
| | ||||
#pragma once | #pragma once | ||||
#include <asio.hpp> | |||||
#if ASIO_VERSION >= 101200 | #if ASIO_VERSION >= 101200 | ||||
#include "asio_task_1.12.0.inl" | #include "asio_task_1.12.0.inl" | ||||
#else | #else |
#pragma once | #pragma once | ||||
#define LIB_RESUMEF_VERSION 20300 // 2.3.0 | |||||
#define LIB_RESUMEF_VERSION 20301 // 2.3.1 | |||||
#if defined(RESUMEF_MODULE_EXPORT) | #if defined(RESUMEF_MODULE_EXPORT) | ||||
#define RESUMEF_NS export namespace resumef | #define RESUMEF_NS export namespace resumef |
_scheduler_ptr = new scheduler_t; | _scheduler_ptr = new scheduler_t; | ||||
th_scheduler_ptr = _scheduler_ptr; | th_scheduler_ptr = _scheduler_ptr; | ||||
} | } | ||||
else | |||||
{ | |||||
_scheduler_ptr = nullptr; | |||||
} | |||||
#endif | #endif | ||||
} | } | ||||
{ | { | ||||
_runing_states.reserve(1024); | _runing_states.reserve(1024); | ||||
_cached_states.reserve(1024); | _cached_states.reserve(1024); | ||||
#if RESUMEF_ENABLE_MULT_SCHEDULER | |||||
if (th_scheduler_ptr == nullptr) | |||||
th_scheduler_ptr = this; | |||||
#endif | |||||
} | } | ||||
scheduler_t::~scheduler_t() | scheduler_t::~scheduler_t() | ||||
void scheduler_t::add_initial(state_base_t* sptr) | void scheduler_t::add_initial(state_base_t* sptr) | ||||
{ | { | ||||
scoped_lock<spinlock, lock_type> __guard(_lock_ready, _lock_running); | |||||
scoped_lock<spinlock, spinlock> __guard(_lock_ready, _lock_running); | |||||
_runing_states.emplace_back(sptr); | |||||
_ready_task.try_emplace(sptr, nullptr); | _ready_task.try_emplace(sptr, nullptr); | ||||
_runing_states.emplace_back(sptr); | |||||
} | } | ||||
void scheduler_t::add_await(state_base_t* sptr) | void scheduler_t::add_await(state_base_t* sptr) | ||||
{ | { | ||||
if (sptr->is_ready()) | if (sptr->is_ready()) | ||||
{ | { | ||||
scoped_lock<lock_type> __guard(_lock_running); | |||||
scoped_lock<spinlock> __guard(_lock_running); | |||||
_runing_states.emplace_back(sptr); | _runing_states.emplace_back(sptr); | ||||
} | } | ||||
} | } | ||||
if (sptr->has_handler()) | if (sptr->has_handler()) | ||||
{ | { | ||||
scoped_lock<lock_type> __guard(_lock_running); | |||||
scoped_lock<spinlock> __guard(_lock_running); | |||||
_runing_states.emplace_back(sptr); | _runing_states.emplace_back(sptr); | ||||
} | } | ||||
} | } | ||||
void scheduler_t::add_generator(state_base_t* sptr) | void scheduler_t::add_generator(state_base_t* sptr) | ||||
{ | { | ||||
scoped_lock<lock_type> __guard(_lock_running); | |||||
scoped_lock<spinlock> __guard(_lock_running); | |||||
_runing_states.emplace_back(sptr); | _runing_states.emplace_back(sptr); | ||||
} | } | ||||
} | } | ||||
if (sptr->has_handler()) | if (sptr->has_handler()) | ||||
{ | { | ||||
scoped_lock<lock_type> __guard(_lock_running); | |||||
scoped_lock<spinlock> __guard(_lock_running); | |||||
_runing_states.emplace_back(sptr); | _runing_states.emplace_back(sptr); | ||||
} | } | ||||
} | } | ||||
/* | /* | ||||
void scheduler_t::cancel_all_task_() | void scheduler_t::cancel_all_task_() | ||||
{ | { | ||||
scoped_lock<spinlock, lock_type> __guard(_lock_ready, _lock_running); | |||||
scoped_lock<spinlock, spinlock> __guard(_lock_ready, _lock_running); | |||||
this->_ready_task.clear(); | this->_ready_task.clear(); | ||||
this->_runing_states.clear(); | this->_runing_states.clear(); | ||||
void scheduler_t::run_one_batch() | void scheduler_t::run_one_batch() | ||||
{ | { | ||||
#if RESUMEF_ENABLE_MULT_SCHEDULER | |||||
if (th_scheduler_ptr == nullptr) | |||||
th_scheduler_ptr = this; | |||||
#endif | |||||
this->_timer->update(); | this->_timer->update(); | ||||
{ | { | ||||
scoped_lock<lock_type> __guard(_lock_running); | |||||
scoped_lock<spinlock> __guard(_lock_running); | |||||
if (_runing_states.empty()) | if (_runing_states.empty()) | ||||
return; | return; | ||||
using lock_type = std::recursive_mutex; | using lock_type = std::recursive_mutex; | ||||
using task_dictionary_type = std::unordered_map<state_base_t*, std::unique_ptr<task_base_t>>; | using task_dictionary_type = std::unordered_map<state_base_t*, std::unique_ptr<task_base_t>>; | ||||
mutable lock_type _lock_running; | |||||
mutable spinlock _lock_running; | |||||
state_vector _runing_states; | state_vector _runing_states; | ||||
state_vector _cached_states; | state_vector _cached_states; | ||||
inline bool empty() const | inline bool empty() const | ||||
{ | { | ||||
scoped_lock<spinlock, lock_type> __guard(_lock_ready, _lock_running); | |||||
scoped_lock<spinlock, spinlock> __guard(_lock_ready, _lock_running); | |||||
return _ready_task.empty() && _runing_states.empty() && _timer->empty(); | return _ready_task.empty() && _runing_states.empty() && _timer->empty(); | ||||
} | } | ||||
#ifndef _LIBCPP_EXPERIMENTAL_COROUTINE | #ifndef _LIBCPP_EXPERIMENTAL_COROUTINE | ||||
#define _LIBCPP_EXPERIMENTAL_COROUTINE | #define _LIBCPP_EXPERIMENTAL_COROUTINE | ||||
#define _EXPERIMENTAL_COROUTINE_ | |||||
/** | /** | ||||
experimental/coroutine synopsis | experimental/coroutine synopsis | ||||
void resumable_main_resumable() | void resumable_main_resumable() | ||||
{ | { | ||||
resumable_switch(1, 0); | resumable_switch(1, 0); | ||||
//resumable_switch(10, 0); | |||||
//resumable_switch(100, 0); | |||||
resumable_switch(10, 0); | |||||
resumable_switch(100, 0); | |||||
resumable_switch(1000, 0); | resumable_switch(1000, 0); | ||||
resumable_switch(10000, 0); | |||||
resumable_switch(30000, 0); | resumable_switch(30000, 0); | ||||
/* | /* |
{ | { | ||||
(void)argc; | (void)argc; | ||||
(void)argv; | (void)argv; | ||||
resumable_main_layout(); | |||||
return 0; | |||||
//resumable_main_resumable(); | |||||
//return 0; | |||||
//if (argc > 1) | //if (argc > 1) | ||||
// resumable_main_benchmark_asio_client(atoi(argv[1])); | // resumable_main_benchmark_asio_client(atoi(argv[1])); | ||||
resumable_main_modern_cb(); | resumable_main_modern_cb(); | ||||
resumable_main_suspend_always(); | resumable_main_suspend_always(); | ||||
resumable_main_yield_return(); | resumable_main_yield_return(); | ||||
//resumable_main_resumable(); | |||||
resumable_main_resumable(); | |||||
resumable_main_routine(); | resumable_main_routine(); | ||||
resumable_main_exception(); | resumable_main_exception(); | ||||
resumable_main_dynamic_go(); | resumable_main_dynamic_go(); | ||||
//resumable_main_multi_thread(); | |||||
resumable_main_multi_thread(); | |||||
resumable_main_timer(); | resumable_main_timer(); | ||||
//resumable_main_benchmark_mem(); | |||||
resumable_main_benchmark_mem(); | |||||
resumable_main_mutex(); | resumable_main_mutex(); | ||||
resumable_main_event(); | resumable_main_event(); | ||||
resumable_main_event_timeout(); | resumable_main_event_timeout(); | ||||
resumable_main_sleep(); | resumable_main_sleep(); | ||||
resumable_main_when_all(); | resumable_main_when_all(); | ||||
resumable_main_switch_scheduler(); | resumable_main_switch_scheduler(); | ||||
//benchmark_main_channel_passing_next(); | |||||
std::cout << "ALL OK!" << std::endl; | std::cout << "ALL OK!" << std::endl; | ||||
benchmark_main_channel_passing_next(); //这是一个死循环测试 | |||||
return 0; | return 0; | ||||
} | } |
</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"> | ||||
</Link> | </Link> | ||||
</ItemDefinitionGroup> | </ItemDefinitionGroup> | ||||
<ItemGroup> | <ItemGroup> | ||||
<ClCompile Include="..\benchmark\benchmark_asio_echo.cpp"> | |||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild> | |||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild> | |||||
</ClCompile> | |||||
<ClCompile Include="..\benchmark\benchmark_asio_echo.cpp" /> | |||||
<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" /> | ||||
<ClCompile Include="..\librf\src\event.cpp" /> | <ClCompile Include="..\librf\src\event.cpp" /> | ||||
<ClCompile Include="..\librf\src\state.cpp" /> | <ClCompile Include="..\librf\src\state.cpp" /> | ||||
<ClCompile Include="..\librf\src\timer.cpp" /> | <ClCompile Include="..\librf\src\timer.cpp" /> | ||||
<ClCompile Include="..\librf\src\when.cpp" /> | <ClCompile Include="..\librf\src\when.cpp" /> | ||||
<ClCompile Include="..\tutorial\test_async_cb.cpp"> | |||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild> | |||||
</ClCompile> | |||||
<ClCompile Include="..\tutorial\test_async_channel.cpp"> | |||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild> | |||||
</ClCompile> | |||||
<ClCompile Include="..\tutorial\test_async_channel_mult_thread.cpp"> | |||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild> | |||||
</ClCompile> | |||||
<ClCompile Include="..\tutorial\test_async_dynamic_go.cpp"> | |||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild> | |||||
</ClCompile> | |||||
<ClCompile Include="..\tutorial\test_async_event.cpp"> | |||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild> | |||||
</ClCompile> | |||||
<ClCompile Include="..\tutorial\test_async_event_timeout.cpp"> | |||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild> | |||||
</ClCompile> | |||||
<ClCompile Include="..\tutorial\test_async_exception.cpp"> | |||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild> | |||||
</ClCompile> | |||||
<ClCompile Include="..\tutorial\test_async_cb.cpp" /> | |||||
<ClCompile Include="..\tutorial\test_async_channel.cpp" /> | |||||
<ClCompile Include="..\tutorial\test_async_channel_mult_thread.cpp" /> | |||||
<ClCompile Include="..\tutorial\test_async_dynamic_go.cpp" /> | |||||
<ClCompile Include="..\tutorial\test_async_event.cpp" /> | |||||
<ClCompile Include="..\tutorial\test_async_event_timeout.cpp" /> | |||||
<ClCompile Include="..\tutorial\test_async_exception.cpp" /> | |||||
<ClCompile Include="..\tutorial\test_async_memory_layout.cpp" /> | <ClCompile Include="..\tutorial\test_async_memory_layout.cpp" /> | ||||
<ClCompile Include="..\tutorial\test_async_modern_cb.cpp"> | |||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild> | |||||
</ClCompile> | |||||
<ClCompile Include="..\tutorial\test_async_multi_thread.cpp"> | |||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild> | |||||
</ClCompile> | |||||
<ClCompile Include="..\tutorial\test_async_mutex.cpp"> | |||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild> | |||||
</ClCompile> | |||||
<ClCompile Include="..\tutorial\test_async_resumable.cpp"> | |||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild> | |||||
</ClCompile> | |||||
<ClCompile Include="..\tutorial\test_async_routine.cpp"> | |||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild> | |||||
</ClCompile> | |||||
<ClCompile Include="..\tutorial\test_async_sleep.cpp"> | |||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild> | |||||
</ClCompile> | |||||
<ClCompile Include="..\tutorial\test_async_suspend_always.cpp"> | |||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild> | |||||
</ClCompile> | |||||
<ClCompile Include="..\tutorial\test_async_switch_scheduler.cpp"> | |||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild> | |||||
</ClCompile> | |||||
<ClCompile Include="..\tutorial\test_async_timer.cpp"> | |||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild> | |||||
</ClCompile> | |||||
<ClCompile Include="..\tutorial\test_async_when_all.cpp"> | |||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild> | |||||
</ClCompile> | |||||
<ClCompile Include="..\tutorial\test_async_modern_cb.cpp" /> | |||||
<ClCompile Include="..\tutorial\test_async_multi_thread.cpp" /> | |||||
<ClCompile Include="..\tutorial\test_async_mutex.cpp" /> | |||||
<ClCompile Include="..\tutorial\test_async_resumable.cpp" /> | |||||
<ClCompile Include="..\tutorial\test_async_routine.cpp" /> | |||||
<ClCompile Include="..\tutorial\test_async_sleep.cpp" /> | |||||
<ClCompile Include="..\tutorial\test_async_suspend_always.cpp" /> | |||||
<ClCompile Include="..\tutorial\test_async_switch_scheduler.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="..\tutorial\test_async_yield_return.cpp" /> | ||||
<ClCompile Include="librf.cpp"> | <ClCompile Include="librf.cpp"> | ||||
<BasicRuntimeChecks Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Default</BasicRuntimeChecks> | <BasicRuntimeChecks Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Default</BasicRuntimeChecks> |