支持以下平台和编译器: | 支持以下平台和编译器: | ||||
Windows: 使用VS2017/VS2019/clang 9 编译 | |||||
Windows: 使用VS2017/VS2019编译(clang在兼容msvc模式下不支持异常,不再支持clang) | |||||
Android: 使用NDK 20.1 自带的clang编译 | Android: 使用NDK 20.1 自带的clang编译 | ||||
Mac: 使用XCode 11.2.1 自带的apple-clang编译 | Mac: 使用XCode 11.2.1 自带的apple-clang编译 | ||||
Ubuntu: 使用GCC 10.0.1/clang 9 编译(2020-04-18:mutex ranged lock failed) | Ubuntu: 使用GCC 10.0.1/clang 9 编译(2020-04-18:mutex ranged lock failed) |
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 = 2000000; | |||||
const size_t N = 10000000; | |||||
const size_t LOOP_COUNT = 50; | const size_t LOOP_COUNT = 50; | ||||
std::atomic<size_t> globalValue{0}; | std::atomic<size_t> globalValue{0}; |
template<class _PromiseT, class _Timeout, typename = std::enable_if_t<traits::is_promise_v<_PromiseT>>> | template<class _PromiseT, class _Timeout, typename = std::enable_if_t<traits::is_promise_v<_PromiseT>>> | ||||
bool await_suspend2(coroutine_handle<_PromiseT> handler, const _Timeout& cb) | bool await_suspend2(coroutine_handle<_PromiseT> handler, const _Timeout& cb) | ||||
{ | { | ||||
(void)cb; | |||||
detail::event_v2_impl* evt = _event; | detail::event_v2_impl* evt = _event; | ||||
scoped_lock<detail::event_v2_impl::lock_type> lock_(evt->_lock); | scoped_lock<detail::event_v2_impl::lock_type> lock_(evt->_lock); | ||||
template<class _PromiseT, class _Timeout, typename = std::enable_if_t<traits::is_promise_v<_PromiseT>>> | template<class _PromiseT, class _Timeout, typename = std::enable_if_t<traits::is_promise_v<_PromiseT>>> | ||||
bool await_suspend2(coroutine_handle<_PromiseT> handler, const _Timeout& cb) | bool await_suspend2(coroutine_handle<_PromiseT> handler, const _Timeout& cb) | ||||
{ | { | ||||
(void)cb; | |||||
using ref_lock_type = std::reference_wrapper<detail::event_v2_impl::lock_type>; | using ref_lock_type = std::reference_wrapper<detail::event_v2_impl::lock_type>; | ||||
std::vector<ref_lock_type> lockes; | std::vector<ref_lock_type> lockes; | ||||
lockes.reserve(std::distance(_begin, _end)); | lockes.reserve(std::distance(_begin, _end)); | ||||
template<class _PromiseT, class _Timeout, typename = std::enable_if_t<traits::is_promise_v<_PromiseT>>> | template<class _PromiseT, class _Timeout, typename = std::enable_if_t<traits::is_promise_v<_PromiseT>>> | ||||
bool await_suspend2(coroutine_handle<_PromiseT> handler, const _Timeout& cb) | bool await_suspend2(coroutine_handle<_PromiseT> handler, const _Timeout& cb) | ||||
{ | { | ||||
(void)cb; | |||||
intptr_t count = std::distance(_begin, _end); | intptr_t count = std::distance(_begin, _end); | ||||
using ref_lock_type = std::reference_wrapper<detail::event_v2_impl::lock_type>; | using ref_lock_type = std::reference_wrapper<detail::event_v2_impl::lock_type>; |
template<class _PromiseT, class _Timeout, typename = std::enable_if_t<traits::is_promise_v<_PromiseT>>> | template<class _PromiseT, class _Timeout, typename = std::enable_if_t<traits::is_promise_v<_PromiseT>>> | ||||
bool await_suspend2(coroutine_handle<_PromiseT> handler, const _Timeout& cb) | bool await_suspend2(coroutine_handle<_PromiseT> handler, const _Timeout& cb) | ||||
{ | { | ||||
(void)cb; | |||||
_PromiseT& promise = handler.promise(); | _PromiseT& promise = handler.promise(); | ||||
auto* parent = promise.get_state(); | auto* parent = promise.get_state(); | ||||
_root = parent->get_root(); | _root = parent->get_root(); |
(void)argc; | (void)argc; | ||||
(void)argv; | (void)argv; | ||||
//resumable_main_stop_token(); | |||||
//resumable_main_mutex(); | |||||
//return 0; | //return 0; | ||||
//if (argc > 1) | //if (argc > 1) |
for (size_t i = 0; i < 10; ++i) | for (size_t i = 0; i < 10; ++i) | ||||
{ | { | ||||
#ifndef __clang__ | |||||
try | try | ||||
#endif | |||||
{ | { | ||||
//auto val = co_await c.read(); | //auto val = co_await c.read(); | ||||
auto val = co_await c; //第二种从channel读出数据的方法。利用重载operator co_await(),而不是c是一个awaitable_t。 | auto val = co_await c; //第二种从channel读出数据的方法。利用重载operator co_await(),而不是c是一个awaitable_t。 | ||||
std::cout << val.value << ":"; | std::cout << val.value << ":"; | ||||
std::cout << std::endl; | std::cout << std::endl; | ||||
} | } | ||||
#ifndef __clang__ | |||||
catch (resumef::channel_exception& e) | catch (resumef::channel_exception& e) | ||||
{ | { | ||||
//MAX_CHANNEL_QUEUE=0,并且先读后写,会触发read_before_write异常 | //MAX_CHANNEL_QUEUE=0,并且先读后写,会触发read_before_write异常 | ||||
std::cout << e.what() << std::endl; | std::cout << e.what() << std::endl; | ||||
} | } | ||||
#endif | |||||
co_await sleep_for(50ms); | co_await sleep_for(50ms); | ||||
} | } |
{ | { | ||||
for (size_t i = 0; i < cnt; ++i) | for (size_t i = 0; i < cnt; ++i) | ||||
{ | { | ||||
#ifndef __clang__ | |||||
try | try | ||||
#endif | |||||
{ | { | ||||
auto val = co_await c.read(); | auto val = co_await c.read(); | ||||
++gcounter; | ++gcounter; | ||||
} | } | ||||
#endif | #endif | ||||
} | } | ||||
#ifndef __clang__ | |||||
catch (channel_exception& e) | catch (channel_exception& e) | ||||
{ | { | ||||
//MAX_CHANNEL_QUEUE=0,并且先读后写,会触发read_before_write异常 | //MAX_CHANNEL_QUEUE=0,并且先读后写,会触发read_before_write异常 | ||||
scoped_lock<std::mutex> __lock(cout_mutex); | scoped_lock<std::mutex> __lock(cout_mutex); | ||||
std::cout << e.what() << std::endl; | std::cout << e.what() << std::endl; | ||||
} | } | ||||
#endif | |||||
#if OUTPUT_DEBUG | #if OUTPUT_DEBUG | ||||
co_await sleep_for(50ms); | co_await sleep_for(50ms); |
{ | { | ||||
for (intptr_t i = 10; i >= 0; --i) | for (intptr_t i = 10; i >= 0; --i) | ||||
{ | { | ||||
#ifndef __clang__ | |||||
try | try | ||||
#endif | |||||
{ | { | ||||
auto r = co_await async_signal_exception2(i); | auto r = co_await async_signal_exception2(i); | ||||
std::cout << "result is " << r << std::endl; | std::cout << "result is " << r << std::endl; | ||||
} | } | ||||
#ifndef __clang__ | |||||
catch (const std::exception& e) | catch (const std::exception& e) | ||||
{ | { | ||||
std::cout << "exception signal : " << e.what() << std::endl; | std::cout << "exception signal : " << e.what() << std::endl; | ||||
{ | { | ||||
std::cout << "exception signal : who knows?" << std::endl; | std::cout << "exception signal : who knows?" << std::endl; | ||||
} | } | ||||
#endif | |||||
} | } | ||||
} | } | ||||
//支持librf的用法 | //支持librf的用法 | ||||
GO | GO | ||||
{ | { | ||||
#ifndef __clang__ | |||||
try | try | ||||
#endif | |||||
{ | { | ||||
int val = co_await add_async(1, 2, use_librf); | int val = co_await add_async(1, 2, use_librf); | ||||
std::cout << val << std::endl; | std::cout << val << std::endl; | ||||
std::cout << result << std::endl; | std::cout << result << std::endl; | ||||
} | } | ||||
#ifndef __clang__ | |||||
catch (const std::exception & e) | catch (const std::exception & e) | ||||
{ | { | ||||
std::cout << "exception signal : " << e.what() << std::endl; | std::cout << "exception signal : " << e.what() << std::endl; | ||||
{ | { | ||||
std::cout << "exception signal : who knows?" << std::endl; | std::cout << "exception signal : who knows?" << std::endl; | ||||
} | } | ||||
#endif | |||||
}; | }; | ||||
resumef::this_scheduler()->run_until_notask(); | resumef::this_scheduler()->run_until_notask(); |
void resumable_main_mutex() | void resumable_main_mutex() | ||||
{ | { | ||||
//std::cout << "begin resumable_mutex_synch()" << std::endl; | |||||
//resumable_mutex_synch(); | |||||
//std::cout << std::endl; | |||||
std::cout << "begin resumable_mutex_synch()" << std::endl; | |||||
resumable_mutex_synch(); | |||||
std::cout << std::endl; | |||||
//std::cout << "begin resumable_mutex_async()" << std::endl; | |||||
//resumable_mutex_async(); | |||||
//std::cout << std::endl; | |||||
std::cout << "begin resumable_mutex_async()" << std::endl; | |||||
resumable_mutex_async(); | |||||
std::cout << std::endl; | |||||
std::cout << "begin resumable_mutex_lock_range()" << std::endl; | std::cout << "begin resumable_mutex_lock_range()" << std::endl; | ||||
resumable_mutex_lock_range(); | resumable_mutex_lock_range(); |
int64_t result = co_await async_get_long_with_stop(val); | int64_t result = co_await async_get_long_with_stop(val); | ||||
std::cout << result << std::endl; | std::cout << result << std::endl; | ||||
} | } | ||||
catch (std::logic_error& e) | |||||
catch (const std::logic_error& e) | |||||
{ | { | ||||
std::cout << e.what() << std::endl; | std::cout << e.what() << std::endl; | ||||
} | } |
<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>ClangCL</PlatformToolset> | |||||
<PlatformToolset>v142</PlatformToolset> | |||||
<WholeProgramOptimization>true</WholeProgramOptimization> | <WholeProgramOptimization>true</WholeProgramOptimization> | ||||
<CharacterSet>NotSet</CharacterSet> | <CharacterSet>NotSet</CharacterSet> | ||||
</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>ClangCL</PlatformToolset> | |||||
<PlatformToolset>v142</PlatformToolset> | |||||
<WholeProgramOptimization>true</WholeProgramOptimization> | <WholeProgramOptimization>true</WholeProgramOptimization> | ||||
<CharacterSet>NotSet</CharacterSet> | <CharacterSet>NotSet</CharacterSet> | ||||
</PropertyGroup> | </PropertyGroup> | ||||
<DisableSpecificWarnings>4834;4505</DisableSpecificWarnings> | <DisableSpecificWarnings>4834;4505</DisableSpecificWarnings> | ||||
<FunctionLevelLinking>true</FunctionLevelLinking> | <FunctionLevelLinking>true</FunctionLevelLinking> | ||||
<EnableParallelCodeGeneration>true</EnableParallelCodeGeneration> | <EnableParallelCodeGeneration>true</EnableParallelCodeGeneration> | ||||
<RuntimeTypeInfo>true</RuntimeTypeInfo> | |||||
<ExceptionHandling>Async</ExceptionHandling> | |||||
</ClCompile> | </ClCompile> | ||||
<Link> | <Link> | ||||
<SubSystem>Console</SubSystem> | <SubSystem>Console</SubSystem> | ||||
<EnableParallelCodeGeneration>true</EnableParallelCodeGeneration> | <EnableParallelCodeGeneration>true</EnableParallelCodeGeneration> | ||||
<DisableSpecificWarnings>4834;4505</DisableSpecificWarnings> | <DisableSpecificWarnings>4834;4505</DisableSpecificWarnings> | ||||
<FunctionLevelLinking>true</FunctionLevelLinking> | <FunctionLevelLinking>true</FunctionLevelLinking> | ||||
<RuntimeTypeInfo>true</RuntimeTypeInfo> | |||||
<ExceptionHandling>Async</ExceptionHandling> | |||||
</ClCompile> | </ClCompile> | ||||
<Link> | <Link> | ||||
<SubSystem>Console</SubSystem> | <SubSystem>Console</SubSystem> |