@@ -1,94 +1,94 @@ | |||
cmake_minimum_required(VERSION 3.14) | |||
PROJECT(librf) | |||
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") | |||
set(CMAKE_CXX_FLAGS "-std=c++2a -fcoroutines-ts -stdlib=libc++") | |||
elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "AppleClang") | |||
set(CMAKE_CXX_FLAGS "-std=c++2a -fcoroutines-ts") | |||
elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") | |||
set(CMAKE_CXX_FLAGS "/std:c++latest /await /EHsc") | |||
elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") | |||
set(CMAKE_CXX_FLAGS "-std=c++2a -fcoroutines-ts") | |||
endif() | |||
message(STATUS "C++ flags: ${CMAKE_CXX_FLAGS}") | |||
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") | |||
option(OPT_INLINE_STATE "Enable Inline state" ON) | |||
elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "AppleClang") | |||
option(OPT_INLINE_STATE "Enable Inline state" ON) | |||
elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") | |||
option(OPT_INLINE_STATE "Enable Inline state" ON) | |||
else() | |||
option(OPT_INLINE_STATE "Enable Inline state" OFF) | |||
endif() | |||
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") | |||
option(OPT_USE_CONCEPT "Use conecpt instead of enable_if" ON) | |||
elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") | |||
option(OPT_USE_CONCEPT "Use conecpt instead of enable_if" ON) | |||
else() | |||
option(OPT_USE_CONCEPT "Use conecpt instead of enable_if" OFF) | |||
endif() | |||
option(OPT_DEBUG_COUNTER "Debug objects count" OFF) | |||
option(OPT_KEEP_REAL_SIZE "Keep real size in queue" OFF) | |||
#set(RESUMEF_USE_CUSTOM_SPINLOCK "std::mutex") | |||
if(OPT_INLINE_STATE) | |||
set(RESUMEF_INLINE_STATE 1) | |||
endif() | |||
if(OPT_DEBUG_COUNTER) | |||
set(RESUMEF_DEBUG_COUNTER 1) | |||
endif() | |||
if(OPT_USE_CONCEPT) | |||
set(RESUMEF_ENABLE_CONCEPT 1) | |||
endif() | |||
if(OPT_KEEP_REAL_SIZE) | |||
set(_WITH_LOCK_FREE_Q_KEEP_REAL_SIZE 1) | |||
endif() | |||
configure_file( | |||
${PROJECT_SOURCE_DIR}/config.h.in | |||
${PROJECT_SOURCE_DIR}/librf/src/config.h) | |||
include_directories( | |||
${PROJECT_SOURCE_DIR}/librf | |||
) | |||
set(SRC | |||
${PROJECT_SOURCE_DIR}/librf/src/event_v1.cpp | |||
${PROJECT_SOURCE_DIR}/librf/src/event_v2.cpp | |||
${PROJECT_SOURCE_DIR}/librf/src/mutex_v1.cpp | |||
${PROJECT_SOURCE_DIR}/librf/src/mutex_v2.cpp | |||
${PROJECT_SOURCE_DIR}/librf/src/rf_task.cpp | |||
${PROJECT_SOURCE_DIR}/librf/src/scheduler.cpp | |||
${PROJECT_SOURCE_DIR}/librf/src/sleep.cpp | |||
${PROJECT_SOURCE_DIR}/librf/src/state.cpp | |||
${PROJECT_SOURCE_DIR}/librf/src/timer.cpp | |||
${PROJECT_SOURCE_DIR}/librf/src/when_v2.cpp | |||
) | |||
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/lib) | |||
set(LIB_NAME librf) | |||
#add_library(${LIB_NAME} SHARED ${SRC}) | |||
add_library(${LIB_NAME} STATIC ${SRC}) | |||
include_directories( | |||
${PROJECT_SOURCE_DIR}/modern_cb | |||
) | |||
aux_source_directory(${PROJECT_SOURCE_DIR}/tutorial TSRC) | |||
set(TSRC ${TSRC} | |||
${PROJECT_SOURCE_DIR}/benchmark/benchmark_async_mem.cpp | |||
${PROJECT_SOURCE_DIR}/benchmark/benchmark_channel_passing_next.cpp | |||
${PROJECT_SOURCE_DIR}/test_librf.cpp | |||
) | |||
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/bin) | |||
add_executable(test ${TSRC}) | |||
target_link_libraries(test ${LIB_NAME}) | |||
cmake_minimum_required(VERSION 3.10) | |||
project(librf) | |||
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") | |||
set(CMAKE_CXX_FLAGS "-std=c++2a -fcoroutines-ts -stdlib=libc++") | |||
elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "AppleClang") | |||
set(CMAKE_CXX_FLAGS "-std=c++2a -fcoroutines-ts") | |||
elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") | |||
set(CMAKE_CXX_FLAGS "/std:c++latest /await /EHsc") | |||
elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") | |||
set(CMAKE_CXX_FLAGS "-std=c++2a -fcoroutines -pthread") | |||
endif() | |||
message(STATUS "C++ flags: ${CMAKE_CXX_FLAGS}") | |||
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") | |||
option(OPT_INLINE_STATE "Enable Inline state" ON) | |||
elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "AppleClang") | |||
option(OPT_INLINE_STATE "Enable Inline state" ON) | |||
elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") | |||
option(OPT_INLINE_STATE "Enable Inline state" ON) | |||
else() | |||
option(OPT_INLINE_STATE "Enable Inline state" OFF) | |||
endif() | |||
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") | |||
option(OPT_USE_CONCEPT "Use conecpt instead of enable_if" ON) | |||
elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") | |||
option(OPT_USE_CONCEPT "Use conecpt instead of enable_if" OFF) | |||
else() | |||
option(OPT_USE_CONCEPT "Use conecpt instead of enable_if" OFF) | |||
endif() | |||
option(OPT_DEBUG_COUNTER "Debug objects count" OFF) | |||
option(OPT_KEEP_REAL_SIZE "Keep real size in queue" OFF) | |||
#set(RESUMEF_USE_CUSTOM_SPINLOCK "std::mutex") | |||
if(OPT_INLINE_STATE) | |||
set(RESUMEF_INLINE_STATE 1) | |||
endif() | |||
if(OPT_DEBUG_COUNTER) | |||
set(RESUMEF_DEBUG_COUNTER 1) | |||
endif() | |||
if(OPT_USE_CONCEPT) | |||
set(RESUMEF_ENABLE_CONCEPT 1) | |||
endif() | |||
if(OPT_KEEP_REAL_SIZE) | |||
set(_WITH_LOCK_FREE_Q_KEEP_REAL_SIZE 1) | |||
endif() | |||
configure_file( | |||
${PROJECT_SOURCE_DIR}/config.h.in | |||
${PROJECT_SOURCE_DIR}/librf/src/config.h) | |||
include_directories( | |||
${PROJECT_SOURCE_DIR}/librf | |||
) | |||
set(SRC | |||
${PROJECT_SOURCE_DIR}/librf/src/event_v1.cpp | |||
${PROJECT_SOURCE_DIR}/librf/src/event_v2.cpp | |||
${PROJECT_SOURCE_DIR}/librf/src/mutex_v1.cpp | |||
${PROJECT_SOURCE_DIR}/librf/src/mutex_v2.cpp | |||
${PROJECT_SOURCE_DIR}/librf/src/rf_task.cpp | |||
${PROJECT_SOURCE_DIR}/librf/src/scheduler.cpp | |||
${PROJECT_SOURCE_DIR}/librf/src/sleep.cpp | |||
${PROJECT_SOURCE_DIR}/librf/src/state.cpp | |||
${PROJECT_SOURCE_DIR}/librf/src/timer.cpp | |||
${PROJECT_SOURCE_DIR}/librf/src/when_v2.cpp | |||
) | |||
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/lib) | |||
set(LIB_NAME librf) | |||
#add_library(${LIB_NAME} SHARED ${SRC}) | |||
add_library(${LIB_NAME} STATIC ${SRC}) | |||
include_directories( | |||
${PROJECT_SOURCE_DIR}/modern_cb | |||
) | |||
aux_source_directory(${PROJECT_SOURCE_DIR}/tutorial TSRC) | |||
set(TSRC ${TSRC} | |||
${PROJECT_SOURCE_DIR}/benchmark/benchmark_async_mem.cpp | |||
${PROJECT_SOURCE_DIR}/benchmark/benchmark_channel_passing_next.cpp | |||
${PROJECT_SOURCE_DIR}/test_librf.cpp | |||
) | |||
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/bin) | |||
add_executable(rf_tutorial ${TSRC}) | |||
target_link_libraries(rf_tutorial ${LIB_NAME}) |
@@ -9,7 +9,7 @@ | |||
const size_t N = 2000000; | |||
const size_t LOOP_COUNT = 50; | |||
volatile size_t globalValue = 0; | |||
std::atomic<size_t> globalValue{0}; | |||
void resumable_main_benchmark_mem(bool wait_key) | |||
{ |
@@ -26,6 +26,20 @@ static future_t<> passing_next(channel_t<intptr_t> rd, channel_t<intptr_t> wr) | |||
} | |||
} | |||
static future_t<> passing_loop_all(channel_t<intptr_t> head, channel_t<intptr_t> tail) | |||
{ | |||
for (int i = 0; i < LoopCount; ++i) | |||
{ | |||
auto tstart = high_resolution_clock::now(); | |||
co_await(head << 0); | |||
intptr_t value = co_await tail; | |||
auto dt = duration_cast<duration<double>>(high_resolution_clock::now() - tstart).count(); | |||
std::cout << value << " cost time " << dt << "s" << std::endl; | |||
} | |||
} | |||
void benchmark_main_channel_passing_next() | |||
{ | |||
channel_t<intptr_t> head{1}; | |||
@@ -39,6 +53,9 @@ void benchmark_main_channel_passing_next() | |||
in = tail; | |||
} | |||
#if defined(__GNUC__) | |||
go passing_loop_all(head, tail); | |||
#else | |||
GO | |||
{ | |||
for (int i = 0; i < LoopCount; ++i) | |||
@@ -52,6 +69,7 @@ void benchmark_main_channel_passing_next() | |||
std::cout << value << " cost time " << dt << "s" << std::endl; | |||
} | |||
}; | |||
#endif | |||
this_scheduler()->run_until_notask(); | |||
} |
@@ -33,7 +33,7 @@ | |||
#include <thread> | |||
#include <iostream> | |||
#include <assert.h> | |||
#if defined(__clang__) | |||
#if defined(__clang__) || defined(__GNUC__) | |||
#include "src/unix/coroutine.h" //编译器内建的协程函数,MSVC和clang不一样 | |||
#else | |||
#include <experimental/coroutine> |
@@ -1,27 +1,27 @@ | |||
#pragma once | |||
#ifndef RESUMEF_INLINE_STATE | |||
#if defined(__clang__) || defined(_MSC_VER) | |||
#define RESUMEF_INLINE_STATE 1 | |||
#else | |||
#define RESUMEF_INLINE_STATE 1 | |||
#endif //defined(__clang__) || defined(_MSC_VER) | |||
#endif //RESUMEF_INLINE_STATE | |||
#ifndef RESUMEF_DEBUG_COUNTER | |||
/* #undef RESUMEF_DEBUG_COUNTER */ | |||
#endif //RESUMEF_DEBUG_COUNTER | |||
#ifndef RESUMEF_ENABLE_CONCEPT | |||
#ifdef __cpp_lib_concepts | |||
#define RESUMEF_ENABLE_CONCEPT 0 | |||
#else | |||
#define RESUMEF_ENABLE_CONCEPT 0 | |||
#endif //#ifdef __cpp_lib_concepts | |||
#endif //#ifndef RESUMEF_ENABLE_CONCEPT | |||
#ifndef _WITH_LOCK_FREE_Q_KEEP_REAL_SIZE | |||
/* #undef _WITH_LOCK_FREE_Q_KEEP_REAL_SIZE */ | |||
#endif //_WITH_LOCK_FREE_Q_KEEP_REAL_SIZE | |||
/* #undef RESUMEF_USE_CUSTOM_SPINLOCK */ | |||
#pragma once | |||
#ifndef RESUMEF_INLINE_STATE | |||
#if defined(__clang__) || defined(_MSC_VER) | |||
/* #undef RESUMEF_INLINE_STATE */ | |||
#else | |||
/* #undef RESUMEF_INLINE_STATE */ | |||
#endif //defined(__clang__) || defined(_MSC_VER) | |||
#endif //RESUMEF_INLINE_STATE | |||
#ifndef RESUMEF_DEBUG_COUNTER | |||
/* #undef RESUMEF_DEBUG_COUNTER */ | |||
#endif //RESUMEF_DEBUG_COUNTER | |||
#ifndef RESUMEF_ENABLE_CONCEPT | |||
#ifdef __cpp_lib_concepts | |||
/* #undef RESUMEF_ENABLE_CONCEPT */ | |||
#else | |||
/* #undef RESUMEF_ENABLE_CONCEPT */ | |||
#endif //#ifdef __cpp_lib_concepts | |||
#endif //#ifndef RESUMEF_ENABLE_CONCEPT | |||
#ifndef _WITH_LOCK_FREE_Q_KEEP_REAL_SIZE | |||
/* #undef _WITH_LOCK_FREE_Q_KEEP_REAL_SIZE */ | |||
#endif //_WITH_LOCK_FREE_Q_KEEP_REAL_SIZE | |||
/* #undef RESUMEF_USE_CUSTOM_SPINLOCK */ |
@@ -160,7 +160,7 @@ namespace resumef | |||
(void)e; | |||
std::terminate(); | |||
} | |||
#ifdef __clang__ | |||
#if defined(__clang__) || defined(__GNUC__) | |||
void unhandled_exception() | |||
{ | |||
std::terminate(); |
@@ -25,7 +25,7 @@ namespace resumef | |||
* @brief 在析构的时候自动解锁mutex_t的辅助类。 | |||
*/ | |||
template<class... _Mtxs> | |||
struct [[nodiscard]] batch_unlock_t; | |||
struct batch_unlock_t; | |||
/** | |||
* @brief 支持递归的锁。 |
@@ -475,7 +475,7 @@ namespace resumef | |||
for (int cnt = rand() % (1 + _mutex.size()); cnt >= 0; --cnt) | |||
{ | |||
std::this_thread::yield(); //还要考虑多线程里运行的情况 | |||
co_await ::resumef::yield(); | |||
co_await yield_awaitor{}; | |||
} | |||
} | |||
future_t<> _ReturnValue() const; | |||
@@ -489,7 +489,7 @@ namespace resumef | |||
}; | |||
template<class... _Mtxs> | |||
struct [[nodiscard]] batch_unlock_t | |||
struct batch_unlock_t | |||
{ | |||
mutex_t::_MutexAwaitAssembleT _MAA; | |||
@@ -534,13 +534,15 @@ namespace resumef | |||
co_return std::move(unlock_guard); | |||
} | |||
#ifndef __GNUC__ | |||
template<class... _Mtxs, typename> | |||
inline future_t<> mutex_t::lock(adopt_manual_unlock_t, _Mtxs&... mtxs) | |||
{ | |||
mutex_t::_MutexAwaitAssembleT _MAA{ root_state(), mtxs... }; | |||
co_await detail::mutex_lock_await_lock_impl::_Lock_range(_MAA); | |||
} | |||
#endif | |||
template<class... _Mtxs, typename> | |||
inline future_t<> mutex_t::unlock(_Mtxs&... mtxs) | |||
{ |
@@ -30,7 +30,7 @@ namespace resumef | |||
template <typename _Uty> | |||
_Uty&& await_transform(_Uty&& _Whatever) noexcept; | |||
void set_exception(std::exception_ptr e); | |||
#ifdef __clang__ | |||
#if defined(__clang__) || defined(__GNUC__) | |||
void unhandled_exception(); //If the coroutine ends with an uncaught exception, it performs the following: | |||
#endif | |||
future_type get_return_object() noexcept; |
@@ -73,7 +73,7 @@ namespace resumef | |||
this->get_state()->set_exception(std::move(e)); | |||
} | |||
#ifdef __clang__ | |||
#if defined(__clang__) || defined(__GNUC__) | |||
template <typename _Ty> | |||
inline void promise_impl_t<_Ty>::unhandled_exception() | |||
{ |
@@ -27,7 +27,7 @@ namespace resumef | |||
{ | |||
if (classname) | |||
{ | |||
#if __clang__ | |||
#if defined(__clang__) || defined(__GNUC__) | |||
#define sprintf_s sprintf | |||
#endif | |||
sprintf_s(sz_future_error_buffer, "%s, code=%s", classname, future_error_string[(size_t)(fe)]); |
@@ -150,7 +150,7 @@ namespace resumef | |||
//msvc认为是constexpr表达式(不写还给警告),然而,clang不这么认为。 | |||
//放弃constexpr,反正合格的编译器都会优化掉这个if判断的。 | |||
if | |||
#ifndef __clang__ | |||
#ifdef _MSC_VER | |||
constexpr | |||
#endif | |||
(_offset_of(state_future_t, _is_future) - _offset_of(state_future_t, _has_value) == 1) |
@@ -52,7 +52,12 @@ template <class P> struct hash<coroutine_handle<P>>; | |||
#include <memory> // for hash<T*> | |||
#include <cstddef> | |||
#include <cassert> | |||
#if defined(__clang__) | |||
#include "clang_builtin.h" | |||
#elif defined(__GNUC__) | |||
#include "gcc_builtin.h" | |||
#endif | |||
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |||
#pragma GCC system_header | |||
@@ -61,6 +66,9 @@ template <class P> struct hash<coroutine_handle<P>>; | |||
#ifndef _LIBCPP_HAS_NO_COROUTINES | |||
namespace std { | |||
#if defined(__GNUC__) | |||
inline | |||
#endif | |||
namespace experimental { | |||
template <class _Tp, class = void> |
@@ -19,7 +19,8 @@ struct LOCK_ASSEMBLE_NAME(lock_impl) | |||
try { | |||
for (; _Next != _Last; ++_Next) | |||
{ | |||
if (!LOCK_ASSEMBLE_AWAIT(_LkN._Try_lock_ref(_LkN[_Next]))) | |||
auto _Result__ = LOCK_ASSEMBLE_AWAIT(_LkN._Try_lock_ref(_LkN[_Next])); | |||
if (!_Result__) | |||
{ // try_lock failed, backout | |||
_Unlock_locks(_First, _Next, _LkN); | |||
LOCK_ASSEMBLE_RETURN(_Next); | |||
@@ -84,7 +85,8 @@ struct LOCK_ASSEMBLE_NAME(lock_impl) | |||
// attempt to lock 2 locks, by first locking _Lk0, and then trying to lock _Lk1 returns whether to try again | |||
LOCK_ASSEMBLE_AWAIT(_LkN._Lock_ref(_LkN[_Idx0])); | |||
try { | |||
if (LOCK_ASSEMBLE_AWAIT(_LkN._Try_lock_ref(_LkN[_Idx1]))) | |||
auto _Result__ = LOCK_ASSEMBLE_AWAIT(_LkN._Try_lock_ref(_LkN[_Idx1])); | |||
if (_Result__) | |||
LOCK_ASSEMBLE_RETURN(false); | |||
} | |||
catch (...) { | |||
@@ -102,10 +104,20 @@ struct LOCK_ASSEMBLE_NAME(lock_impl) | |||
static auto _Lock_nonmember2(_LA& _LkN) ->decltype(_LkN._ReturnValue()) | |||
{ | |||
// lock 2 locks, without deadlock, special case for better codegen and reduced metaprogramming for common case | |||
#if defined(__GNUC__) | |||
for (;;) | |||
{ | |||
auto _Result__ = LOCK_ASSEMBLE_AWAIT(_Lock_attempt_small2(_LkN, 0, 1)); | |||
if (!_Result__) break; | |||
_Result__ = LOCK_ASSEMBLE_AWAIT(_Lock_attempt_small2(_LkN, 1, 0)); | |||
if (!_Result__) break; | |||
} | |||
#else | |||
while (LOCK_ASSEMBLE_AWAIT(_Lock_attempt_small2(_LkN, 0, 1)) && | |||
LOCK_ASSEMBLE_AWAIT(_Lock_attempt_small2(_LkN, 1, 0))) | |||
{ // keep trying | |||
} | |||
#endif | |||
} | |||
template<_LockAssembleT _LA> |
@@ -22,7 +22,8 @@ static future_t<> resumable_wait_event(const event_t & e) | |||
{ | |||
using namespace std::chrono; | |||
if (co_await e.wait() == false) | |||
auto result = co_await e.wait(); | |||
if (result == false) | |||
std::cout << "time out!" << std::endl; | |||
else | |||
std::cout << "event signal!" << std::endl; | |||
@@ -69,7 +70,8 @@ static void test_wait_three() | |||
go[&]() -> future_t<> | |||
{ | |||
if (co_await event_t::wait_all(std::initializer_list<event_t>{ evt1, evt2, evt3 })) | |||
auto result = co_await event_t::wait_all(std::initializer_list<event_t>{ evt1, evt2, evt3 }); | |||
if (result) | |||
std::cout << "all event signal!" << std::endl; | |||
else | |||
std::cout << "time out!" << std::endl; | |||
@@ -125,7 +127,8 @@ static void test_wait_all() | |||
go[&]() -> future_t<> | |||
{ | |||
if (co_await event_t::wait_all(evts)) | |||
auto result = co_await event_t::wait_all(evts); | |||
if (result) | |||
std::cout << "all event signal!" << std::endl; | |||
else | |||
std::cout << "time out!" << std::endl; | |||
@@ -153,7 +156,8 @@ static void test_wait_all_timeout() | |||
go[&]() -> future_t<> | |||
{ | |||
if (co_await event_t::wait_all_for(1000ms, evts)) | |||
auto result = co_await event_t::wait_all_for(1000ms, evts); | |||
if (result) | |||
std::cout << "all event signal!" << std::endl; | |||
else | |||
std::cout << "time out!" << std::endl; |
@@ -35,7 +35,8 @@ void test_wait_timeout_one() | |||
intptr_t counter = 0; | |||
for (;;) | |||
{ | |||
if (co_await evt.wait_for(100ms)) | |||
auto result = co_await evt.wait_for(100ms); | |||
if (result) | |||
break; | |||
++counter; | |||
std::cout << "."; | |||
@@ -137,7 +138,8 @@ void test_wait_timeout_all() | |||
intptr_t counter = 0; | |||
for (;;) | |||
{ | |||
if (co_await event_t::wait_all_for(1500ms, evts)) | |||
auto result = co_await event_t::wait_all_for(1500ms, evts); | |||
if (result) | |||
{ | |||
std::cout << counter << std::endl; | |||
std::cout << "all event signal!" << std::endl; |
@@ -29,7 +29,8 @@ static std::thread async_set_event_one(event_v2::event_t e, std::chrono::millise | |||
static future_t<> resumable_wait_event(event_v2::event_t e, int idx) | |||
{ | |||
if (co_await e) | |||
auto result = co_await e; | |||
if (result) | |||
std::cout << "[" << idx << "]event signal!" << std::endl; | |||
else | |||
std::cout << "[" << idx << "]time out!" << std::endl; | |||
@@ -37,7 +38,8 @@ static future_t<> resumable_wait_event(event_v2::event_t e, int idx) | |||
static future_t<> resumable_wait_timeout(event_v2::event_t e, milliseconds dt, int idx) | |||
{ | |||
if (co_await e.wait_for(dt)) | |||
auto result = co_await e.wait_for(dt); | |||
if (result) | |||
std::cout << "[" << idx << "]event signal!" << std::endl; | |||
else | |||
std::cout << "[" << idx << "]time out!" << std::endl; |
@@ -51,7 +51,7 @@ future_t<int64_t> resumeable_get_long(int64_t x, int64_t y) | |||
using promise_type = typename future_type::promise_type; | |||
using state_type = typename future_type::state_type; | |||
void* frame_ptr = _coro_frame_ptr(); | |||
void* frame_ptr = __builtin_coro_frame(); | |||
auto handler = coroutine_handle<promise_type>::from_address(frame_ptr); | |||
promise_type* promise = &handler.promise(); | |||
state_type* state = handler.promise().get_state(); | |||
@@ -59,10 +59,10 @@ future_t<int64_t> resumeable_get_long(int64_t x, int64_t y) | |||
std::cout << " future size=" << sizeof(future_type) << " / " << _Align_size<future_type>() << std::endl; | |||
std::cout << " promise size=" << sizeof(promise_type) << " / " << _Align_size<promise_type>() << std::endl; | |||
std::cout << " state size=" << sizeof(state_type) << " / "<< _Align_size<state_type>() << std::endl; | |||
std::cout << " frame size=" << _coro_frame_size() << ", alloc size=" << state->get_alloc_size() << std::endl; | |||
std::cout << " frame size=" << __builtin_coro_size() << ", alloc size=" << state->get_alloc_size() << std::endl; | |||
std::cout << " frame ptr=" << frame_ptr << "," << (void*)&frame_ptr << std::endl; | |||
std::cout << " frame end=" << (void*)((char*)(frame_ptr)+_coro_frame_size()) << std::endl; | |||
std::cout << " frame end=" << (void*)((char*)(frame_ptr)+__builtin_coro_size()) << std::endl; | |||
std::cout << " promise ptr=" << promise << "," << (void*)&promise << std::endl; | |||
std::cout << " handle ptr=" << handler.address() << "," << (void*)&handler << std::endl; | |||
std::cout << " state ptr=" << state << "," << (void*)&state << std::endl; | |||
@@ -90,7 +90,7 @@ future_t<> resumable_get_long_2(int64_t a, int64_t b, int64_t c) | |||
using promise_type = typename future_type::promise_type; | |||
using state_type = typename future_type::state_type; | |||
void* frame_ptr = _coro_frame_ptr(); | |||
void* frame_ptr = __builtin_coro_frame(); | |||
auto handler = coroutine_handle<promise_type>::from_address(frame_ptr); | |||
promise_type * promise = &handler.promise(); | |||
state_type * state = handler.promise().get_state(); | |||
@@ -98,10 +98,10 @@ future_t<> resumable_get_long_2(int64_t a, int64_t b, int64_t c) | |||
std::cout << " future size=" << sizeof(future_type) << " / " << _Align_size<future_type>() << std::endl; | |||
std::cout << " promise size=" << sizeof(promise_type) << " / " << _Align_size<promise_type>() << std::endl; | |||
std::cout << " state size=" << sizeof(state_type) << " / "<< _Align_size<state_type>() << std::endl; | |||
std::cout << " frame size=" << _coro_frame_size() << ", alloc size=" << state->get_alloc_size() << std::endl; | |||
std::cout << " frame size=" << __builtin_coro_size() << ", alloc size=" << state->get_alloc_size() << std::endl; | |||
std::cout << " frame ptr=" << frame_ptr << ","<< (void*)&frame_ptr << std::endl; | |||
std::cout << " frame end=" << (void *)((char*)(frame_ptr) + _coro_frame_size()) << std::endl; | |||
std::cout << " frame end=" << (void *)((char*)(frame_ptr) + __builtin_coro_size()) << std::endl; | |||
std::cout << " promise ptr=" << promise << "," << (void *)&promise << std::endl; | |||
std::cout << " handle ptr=" << handler.address() << "," << (void*)&handler << std::endl; | |||
std::cout << " state ptr=" << state << "," << (void*)&state << std::endl; |
@@ -61,8 +61,12 @@ static future_t<> test_mutex_try_push(size_t idx) | |||
for (size_t i = 0; i < N; ++i) | |||
{ | |||
{ | |||
while (!co_await g_lock.try_lock()) | |||
for (;;) | |||
{ | |||
auto result = co_await g_lock.try_lock(); | |||
if (result) break; | |||
co_await yield(); | |||
} | |||
++g_counter; | |||
std::cout << "push:" << g_counter << " on " << idx << std::endl; | |||
@@ -79,8 +83,12 @@ static future_t<> test_mutex_timeout_push(size_t idx) | |||
for (size_t i = 0; i < N; ++i) | |||
{ | |||
{ | |||
while (!co_await g_lock.try_lock_for(10ms)) | |||
for (;;) | |||
{ | |||
auto result = co_await g_lock.try_lock_for(10ms); | |||
if (result) break; | |||
co_await yield(); | |||
} | |||
++g_counter; | |||
std::cout << "push:" << g_counter << " on " << idx << std::endl; |
@@ -16,7 +16,7 @@ future_t<> test_routine_use_timer() | |||
{ | |||
co_await resumef::sleep_for(100ms); | |||
std::cout << "timer after 100ms" << std::endl; | |||
std::cout << "1:frame=" << _coro_frame_ptr() << std::endl; | |||
std::cout << "1:frame=" << __builtin_coro_frame() << std::endl; | |||
} | |||
} | |||
@@ -25,11 +25,11 @@ future_t<> test_routine_use_timer_2() | |||
std::cout << "test_routine_use_timer_2" << std::endl; | |||
co_await test_routine_use_timer(); | |||
std::cout << "2:frame=" << _coro_frame_ptr() << std::endl; | |||
std::cout << "2:frame=" << __builtin_coro_frame() << std::endl; | |||
co_await test_routine_use_timer(); | |||
std::cout << "2:frame=" << _coro_frame_ptr() << std::endl; | |||
std::cout << "2:frame=" << __builtin_coro_frame() << std::endl; | |||
co_await test_routine_use_timer(); | |||
std::cout << "2:frame=" << _coro_frame_ptr() << std::endl; | |||
std::cout << "2:frame=" << __builtin_coro_frame() << std::endl; | |||
} | |||
void resumable_main_routine() |
@@ -38,7 +38,8 @@ void test_wait_all_events_with_signal_by_sleep() | |||
go[&]() -> future_t<> | |||
{ | |||
if (co_await event_t::wait_all(evts)) | |||
auto result = co_await event_t::wait_all(evts); | |||
if (result) | |||
std::cout << "all event signal!" << std::endl; | |||
else | |||
std::cout << "time out!" << std::endl; |
@@ -88,6 +88,18 @@ static future_t<> resumable_get_long_switch_scheduler(int64_t val, channel_t<boo | |||
(void)c_done.write(true); | |||
} | |||
static future_t<> resumable_main_switch_scheduler_fix_gcc_bugs(std::thread & other, channel_t<bool> c_done) | |||
{ | |||
co_await c_done; //第一次等待,等待run_in_thread准备好了 | |||
std::cout << "other thread = " << other.get_id(); | |||
std::cout << ", sch_in_thread = " << sch_in_thread << std::endl; | |||
go resumable_get_long_switch_scheduler(1, c_done); //开启另外一个协程 | |||
//co_await resumable_get_long(3, c_done); | |||
co_await c_done; //等待新的协程运行完毕,从而保证主线程的协程不会提早退出 | |||
} | |||
void resumable_main_switch_scheduler() | |||
{ | |||
sch_in_main = this_scheduler(); | |||
@@ -98,6 +110,9 @@ void resumable_main_switch_scheduler() | |||
channel_t<bool> c_done{ 1 }; | |||
std::thread other(&run_in_thread, std::ref(c_done)); | |||
#if defined(__GNUC__) | |||
go resumable_main_switch_scheduler_fix_gcc_bugs(other, c_done); | |||
#else | |||
go[&other, c_done]()->future_t<> | |||
{ | |||
co_await c_done; //第一次等待,等待run_in_thread准备好了 | |||
@@ -108,7 +123,8 @@ void resumable_main_switch_scheduler() | |||
go resumable_get_long_switch_scheduler(1, c_done); //开启另外一个协程 | |||
//co_await resumable_get_long(3, c_done); | |||
co_await c_done; //等待新的协程运行完毕,从而保证主线程的协程不会提早退出 | |||
}; | |||
}; //GCC: internal compiler error: in captures_temporary, at cp/coroutines.cc:2716 | |||
#endif | |||
sch_in_main->run_until_notask(); | |||