From 63f2e1b300261b1031821493f4776f580f4444ff Mon Sep 17 00:00:00 2001 From: tearshark Date: Sat, 18 Apr 2020 11:46:29 +0800 Subject: [PATCH] =?UTF-8?q?=E5=85=BC=E5=AE=B9gcc-10?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CMakeLists.txt | 188 +++++++++---------- benchmark/benchmark_async_mem.cpp | 2 +- benchmark/benchmark_channel_passing_next.cpp | 18 ++ librf/librf.h | 2 +- librf/src/config.h | 54 +++--- librf/src/generator.h | 2 +- librf/src/mutex_v2.h | 2 +- librf/src/mutex_v2.inl | 8 +- librf/src/promise.h | 2 +- librf/src/promise.inl | 2 +- librf/src/scheduler.cpp | 2 +- librf/src/state.h | 2 +- librf/src/unix/coroutine.h | 8 + librf/src/without_deadlock_assemble.inl | 16 +- tutorial/test_async_event.cpp | 12 +- tutorial/test_async_event_timeout.cpp | 6 +- tutorial/test_async_event_v2.cpp | 6 +- tutorial/test_async_memory_layout.cpp | 12 +- tutorial/test_async_mutex.cpp | 12 +- tutorial/test_async_routine.cpp | 8 +- tutorial/test_async_sleep.cpp | 3 +- tutorial/test_async_switch_scheduler.cpp | 18 +- 22 files changed, 229 insertions(+), 156 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 899e782..4b23856 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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}) \ No newline at end of file +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}) \ No newline at end of file diff --git a/benchmark/benchmark_async_mem.cpp b/benchmark/benchmark_async_mem.cpp index 09934f3..7777609 100644 --- a/benchmark/benchmark_async_mem.cpp +++ b/benchmark/benchmark_async_mem.cpp @@ -9,7 +9,7 @@ const size_t N = 2000000; const size_t LOOP_COUNT = 50; -volatile size_t globalValue = 0; +std::atomic globalValue{0}; void resumable_main_benchmark_mem(bool wait_key) { diff --git a/benchmark/benchmark_channel_passing_next.cpp b/benchmark/benchmark_channel_passing_next.cpp index 3e2cc76..fee5def 100644 --- a/benchmark/benchmark_channel_passing_next.cpp +++ b/benchmark/benchmark_channel_passing_next.cpp @@ -26,6 +26,20 @@ static future_t<> passing_next(channel_t rd, channel_t wr) } } +static future_t<> passing_loop_all(channel_t head, channel_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>(high_resolution_clock::now() - tstart).count(); + std::cout << value << " cost time " << dt << "s" << std::endl; + } +} + void benchmark_main_channel_passing_next() { channel_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(); } diff --git a/librf/librf.h b/librf/librf.h index 535bd5a..378567e 100644 --- a/librf/librf.h +++ b/librf/librf.h @@ -33,7 +33,7 @@ #include #include #include -#if defined(__clang__) +#if defined(__clang__) || defined(__GNUC__) #include "src/unix/coroutine.h" //编译器内建的协程函数,MSVC和clang不一样 #else #include diff --git a/librf/src/config.h b/librf/src/config.h index 6ba374f..9b03415 100644 --- a/librf/src/config.h +++ b/librf/src/config.h @@ -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 */ diff --git a/librf/src/generator.h b/librf/src/generator.h index f3c4c05..bcb8ea0 100644 --- a/librf/src/generator.h +++ b/librf/src/generator.h @@ -160,7 +160,7 @@ namespace resumef (void)e; std::terminate(); } -#ifdef __clang__ +#if defined(__clang__) || defined(__GNUC__) void unhandled_exception() { std::terminate(); diff --git a/librf/src/mutex_v2.h b/librf/src/mutex_v2.h index aad9710..dadced0 100644 --- a/librf/src/mutex_v2.h +++ b/librf/src/mutex_v2.h @@ -25,7 +25,7 @@ namespace resumef * @brief 在析构的时候自动解锁mutex_t的辅助类。 */ template - struct [[nodiscard]] batch_unlock_t; + struct batch_unlock_t; /** * @brief 支持递归的锁。 diff --git a/librf/src/mutex_v2.inl b/librf/src/mutex_v2.inl index 6a218e4..8446700 100644 --- a/librf/src/mutex_v2.inl +++ b/librf/src/mutex_v2.inl @@ -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 - 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 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 inline future_t<> mutex_t::unlock(_Mtxs&... mtxs) { diff --git a/librf/src/promise.h b/librf/src/promise.h index e383920..0f88c37 100644 --- a/librf/src/promise.h +++ b/librf/src/promise.h @@ -30,7 +30,7 @@ namespace resumef template _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; diff --git a/librf/src/promise.inl b/librf/src/promise.inl index e90726d..6c825d3 100644 --- a/librf/src/promise.inl +++ b/librf/src/promise.inl @@ -73,7 +73,7 @@ namespace resumef this->get_state()->set_exception(std::move(e)); } -#ifdef __clang__ +#if defined(__clang__) || defined(__GNUC__) template inline void promise_impl_t<_Ty>::unhandled_exception() { diff --git a/librf/src/scheduler.cpp b/librf/src/scheduler.cpp index aa95e78..fa16988 100644 --- a/librf/src/scheduler.cpp +++ b/librf/src/scheduler.cpp @@ -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)]); diff --git a/librf/src/state.h b/librf/src/state.h index 3a214eb..ceb2d7f 100644 --- a/librf/src/state.h +++ b/librf/src/state.h @@ -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) diff --git a/librf/src/unix/coroutine.h b/librf/src/unix/coroutine.h index d4ff461..e5e5241 100644 --- a/librf/src/unix/coroutine.h +++ b/librf/src/unix/coroutine.h @@ -52,7 +52,12 @@ template struct hash>; #include // for hash #include #include + +#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 struct hash>; #ifndef _LIBCPP_HAS_NO_COROUTINES namespace std { +#if defined(__GNUC__) + inline +#endif namespace experimental { template diff --git a/librf/src/without_deadlock_assemble.inl b/librf/src/without_deadlock_assemble.inl index f976b79..7bef438 100644 --- a/librf/src/without_deadlock_assemble.inl +++ b/librf/src/without_deadlock_assemble.inl @@ -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> diff --git a/tutorial/test_async_event.cpp b/tutorial/test_async_event.cpp index b4e082e..0c8fca6 100644 --- a/tutorial/test_async_event.cpp +++ b/tutorial/test_async_event.cpp @@ -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{ evt1, evt2, evt3 })) + auto result = co_await event_t::wait_all(std::initializer_list{ 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; diff --git a/tutorial/test_async_event_timeout.cpp b/tutorial/test_async_event_timeout.cpp index 5c8664e..7f1d5a0 100644 --- a/tutorial/test_async_event_timeout.cpp +++ b/tutorial/test_async_event_timeout.cpp @@ -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; diff --git a/tutorial/test_async_event_v2.cpp b/tutorial/test_async_event_v2.cpp index b70c56f..9c48e8c 100644 --- a/tutorial/test_async_event_v2.cpp +++ b/tutorial/test_async_event_v2.cpp @@ -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; diff --git a/tutorial/test_async_memory_layout.cpp b/tutorial/test_async_memory_layout.cpp index 6c87046..8c1a8dd 100644 --- a/tutorial/test_async_memory_layout.cpp +++ b/tutorial/test_async_memory_layout.cpp @@ -51,7 +51,7 @@ future_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::from_address(frame_ptr); promise_type* promise = &handler.promise(); state_type* state = handler.promise().get_state(); @@ -59,10 +59,10 @@ future_t resumeable_get_long(int64_t x, int64_t y) std::cout << " future size=" << sizeof(future_type) << " / " << _Align_size() << std::endl; std::cout << " promise size=" << sizeof(promise_type) << " / " << _Align_size() << std::endl; std::cout << " state size=" << sizeof(state_type) << " / "<< _Align_size() << 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::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() << std::endl; std::cout << " promise size=" << sizeof(promise_type) << " / " << _Align_size() << std::endl; std::cout << " state size=" << sizeof(state_type) << " / "<< _Align_size() << 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; diff --git a/tutorial/test_async_mutex.cpp b/tutorial/test_async_mutex.cpp index 4f48500..d7197c6 100644 --- a/tutorial/test_async_mutex.cpp +++ b/tutorial/test_async_mutex.cpp @@ -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; diff --git a/tutorial/test_async_routine.cpp b/tutorial/test_async_routine.cpp index 1685da6..9910906 100644 --- a/tutorial/test_async_routine.cpp +++ b/tutorial/test_async_routine.cpp @@ -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() diff --git a/tutorial/test_async_sleep.cpp b/tutorial/test_async_sleep.cpp index 8571019..bef06a8 100644 --- a/tutorial/test_async_sleep.cpp +++ b/tutorial/test_async_sleep.cpp @@ -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; diff --git a/tutorial/test_async_switch_scheduler.cpp b/tutorial/test_async_switch_scheduler.cpp index 823e47a..778d885 100644 --- a/tutorial/test_async_switch_scheduler.cpp +++ b/tutorial/test_async_switch_scheduler.cpp @@ -88,6 +88,18 @@ static future_t<> resumable_get_long_switch_scheduler(int64_t val, channel_t resumable_main_switch_scheduler_fix_gcc_bugs(std::thread & other, channel_t 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 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();