Browse Source

Merge branch 'master' of https://github.com/tearshark/librf

# Conflicts:
#	CMakeLists.txt
#	librf/src/config.h
tags/2.9.10
tearshark 4 years ago
parent
commit
02a69b586d

+ 2
- 2
CMakeLists.txt View File

elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
set(CMAKE_CXX_FLAGS "/std:c++latest /await /EHsc") set(CMAKE_CXX_FLAGS "/std:c++latest /await /EHsc")
elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
set(CMAKE_CXX_FLAGS "-std=c++2a -fcoroutines")
set(CMAKE_CXX_FLAGS "-std=c++2a -fcoroutines -pthread")
endif() endif()
message(STATUS "C++ flags: ${CMAKE_CXX_FLAGS}") message(STATUS "C++ flags: ${CMAKE_CXX_FLAGS}")
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
option(OPT_USE_CONCEPT "Use conecpt instead of enable_if" ON) option(OPT_USE_CONCEPT "Use conecpt instead of enable_if" ON)
elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
option(OPT_USE_CONCEPT "Use conecpt instead of enable_if" ON)
option(OPT_USE_CONCEPT "Use conecpt instead of enable_if" OFF)
else() else()
option(OPT_USE_CONCEPT "Use conecpt instead of enable_if" OFF) option(OPT_USE_CONCEPT "Use conecpt instead of enable_if" OFF)
endif() endif()

+ 1
- 1
benchmark/benchmark_async_mem.cpp View File

const size_t N = 2000000; const size_t N = 2000000;
const size_t LOOP_COUNT = 50; 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) void resumable_main_benchmark_mem(bool wait_key)
{ {

+ 18
- 0
benchmark/benchmark_channel_passing_next.cpp View File

} }
} }


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() void benchmark_main_channel_passing_next()
{ {
channel_t<intptr_t> head{1}; channel_t<intptr_t> head{1};
in = tail; in = tail;
} }


#if defined(__GNUC__)
go passing_loop_all(head, tail);
#else
GO GO
{ {
for (int i = 0; i < LoopCount; ++i) for (int i = 0; i < LoopCount; ++i)
std::cout << value << " cost time " << dt << "s" << std::endl; std::cout << value << " cost time " << dt << "s" << std::endl;
} }
}; };
#endif


this_scheduler()->run_until_notask(); this_scheduler()->run_until_notask();
} }

+ 1
- 1
librf/librf.h View File

#include <thread> #include <thread>
#include <iostream> #include <iostream>
#include <assert.h> #include <assert.h>
#if defined(__clang__)
#if defined(__clang__) || defined(__GNUC__)
#include "src/unix/coroutine.h" //编译器内建的协程函数,MSVC和clang不一样 #include "src/unix/coroutine.h" //编译器内建的协程函数,MSVC和clang不一样
#else #else
#include <experimental/coroutine> #include <experimental/coroutine>

+ 2
- 2
librf/src/config.h View File



#ifndef RESUMEF_ENABLE_CONCEPT #ifndef RESUMEF_ENABLE_CONCEPT
#ifdef __cpp_lib_concepts #ifdef __cpp_lib_concepts
#define RESUMEF_ENABLE_CONCEPT 1
/* #undef RESUMEF_ENABLE_CONCEPT */
#else #else
#define RESUMEF_ENABLE_CONCEPT 1
/* #undef RESUMEF_ENABLE_CONCEPT */
#endif //#ifdef __cpp_lib_concepts #endif //#ifdef __cpp_lib_concepts
#endif //#ifndef RESUMEF_ENABLE_CONCEPT #endif //#ifndef RESUMEF_ENABLE_CONCEPT



+ 1
- 1
librf/src/generator.h View File

(void)e; (void)e;
std::terminate(); std::terminate();
} }
#ifdef __clang__
#if defined(__clang__) || defined(__GNUC__)
void unhandled_exception() void unhandled_exception()
{ {
std::terminate(); std::terminate();

+ 1
- 1
librf/src/mutex_v2.h View File

* @brief 在析构的时候自动解锁mutex_t的辅助类。 * @brief 在析构的时候自动解锁mutex_t的辅助类。
*/ */
template<class... _Mtxs> template<class... _Mtxs>
struct [[nodiscard]] batch_unlock_t;
struct batch_unlock_t;


/** /**
* @brief 支持递归的锁。 * @brief 支持递归的锁。

+ 5
- 3
librf/src/mutex_v2.inl View File

for (int cnt = rand() % (1 + _mutex.size()); cnt >= 0; --cnt) for (int cnt = rand() % (1 + _mutex.size()); cnt >= 0; --cnt)
{ {
std::this_thread::yield(); //还要考虑多线程里运行的情况 std::this_thread::yield(); //还要考虑多线程里运行的情况
co_await ::resumef::yield();
co_await yield_awaitor{};
} }
} }
future_t<> _ReturnValue() const; future_t<> _ReturnValue() const;
}; };


template<class... _Mtxs> template<class... _Mtxs>
struct [[nodiscard]] batch_unlock_t
struct batch_unlock_t
{ {
mutex_t::_MutexAwaitAssembleT _MAA; mutex_t::_MutexAwaitAssembleT _MAA;


co_return std::move(unlock_guard); co_return std::move(unlock_guard);
} }


#ifndef __GNUC__
template<class... _Mtxs, typename> template<class... _Mtxs, typename>
inline future_t<> mutex_t::lock(adopt_manual_unlock_t, _Mtxs&... mtxs) inline future_t<> mutex_t::lock(adopt_manual_unlock_t, _Mtxs&... mtxs)
{ {
mutex_t::_MutexAwaitAssembleT _MAA{ root_state(), mtxs... }; mutex_t::_MutexAwaitAssembleT _MAA{ root_state(), mtxs... };
co_await detail::mutex_lock_await_lock_impl::_Lock_range(_MAA); co_await detail::mutex_lock_await_lock_impl::_Lock_range(_MAA);
} }

#endif
template<class... _Mtxs, typename> template<class... _Mtxs, typename>
inline future_t<> mutex_t::unlock(_Mtxs&... mtxs) inline future_t<> mutex_t::unlock(_Mtxs&... mtxs)
{ {

+ 1
- 1
librf/src/promise.h View File

template <typename _Uty> template <typename _Uty>
_Uty&& await_transform(_Uty&& _Whatever) noexcept; _Uty&& await_transform(_Uty&& _Whatever) noexcept;
void set_exception(std::exception_ptr e); 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: void unhandled_exception(); //If the coroutine ends with an uncaught exception, it performs the following:
#endif #endif
future_type get_return_object() noexcept; future_type get_return_object() noexcept;

+ 1
- 1
librf/src/promise.inl View File

this->get_state()->set_exception(std::move(e)); this->get_state()->set_exception(std::move(e));
} }


#ifdef __clang__
#if defined(__clang__) || defined(__GNUC__)
template <typename _Ty> template <typename _Ty>
inline void promise_impl_t<_Ty>::unhandled_exception() inline void promise_impl_t<_Ty>::unhandled_exception()
{ {

+ 1
- 1
librf/src/scheduler.cpp View File

{ {
if (classname) if (classname)
{ {
#if __clang__
#if defined(__clang__) || defined(__GNUC__)
#define sprintf_s sprintf #define sprintf_s sprintf
#endif #endif
sprintf_s(sz_future_error_buffer, "%s, code=%s", classname, future_error_string[(size_t)(fe)]); sprintf_s(sz_future_error_buffer, "%s, code=%s", classname, future_error_string[(size_t)(fe)]);

+ 1
- 1
librf/src/state.h View File

//msvc认为是constexpr表达式(不写还给警告),然而,clang不这么认为。 //msvc认为是constexpr表达式(不写还给警告),然而,clang不这么认为。
//放弃constexpr,反正合格的编译器都会优化掉这个if判断的。 //放弃constexpr,反正合格的编译器都会优化掉这个if判断的。
if if
#ifndef __clang__
#ifdef _MSC_VER
constexpr constexpr
#endif #endif
(_offset_of(state_future_t, _is_future) - _offset_of(state_future_t, _has_value) == 1) (_offset_of(state_future_t, _is_future) - _offset_of(state_future_t, _has_value) == 1)

+ 8
- 0
librf/src/unix/coroutine.h View File

#include <memory> // for hash<T*> #include <memory> // for hash<T*>
#include <cstddef> #include <cstddef>
#include <cassert> #include <cassert>

#if defined(__clang__)
#include "clang_builtin.h" #include "clang_builtin.h"
#elif defined(__GNUC__)
#include "gcc_builtin.h"
#endif


#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
#pragma GCC system_header #pragma GCC system_header
#ifndef _LIBCPP_HAS_NO_COROUTINES #ifndef _LIBCPP_HAS_NO_COROUTINES


namespace std { namespace std {
#if defined(__GNUC__)
inline
#endif
namespace experimental { namespace experimental {


template <class _Tp, class = void> template <class _Tp, class = void>

+ 14
- 2
librf/src/without_deadlock_assemble.inl View File

try { try {
for (; _Next != _Last; ++_Next) 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 { // try_lock failed, backout
_Unlock_locks(_First, _Next, _LkN); _Unlock_locks(_First, _Next, _LkN);
LOCK_ASSEMBLE_RETURN(_Next); LOCK_ASSEMBLE_RETURN(_Next);
// attempt to lock 2 locks, by first locking _Lk0, and then trying to lock _Lk1 returns whether to try again // 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])); LOCK_ASSEMBLE_AWAIT(_LkN._Lock_ref(_LkN[_Idx0]));
try { 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); LOCK_ASSEMBLE_RETURN(false);
} }
catch (...) { catch (...) {
static auto _Lock_nonmember2(_LA& _LkN) ->decltype(_LkN._ReturnValue()) 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 // 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)) && while (LOCK_ASSEMBLE_AWAIT(_Lock_attempt_small2(_LkN, 0, 1)) &&
LOCK_ASSEMBLE_AWAIT(_Lock_attempt_small2(_LkN, 1, 0))) LOCK_ASSEMBLE_AWAIT(_Lock_attempt_small2(_LkN, 1, 0)))
{ // keep trying { // keep trying
} }
#endif
} }
template<_LockAssembleT _LA> template<_LockAssembleT _LA>

+ 8
- 4
tutorial/test_async_event.cpp View File

{ {
using namespace std::chrono; 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; std::cout << "time out!" << std::endl;
else else
std::cout << "event signal!" << std::endl; std::cout << "event signal!" << std::endl;
go[&]() -> future_t<> 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; std::cout << "all event signal!" << std::endl;
else else
std::cout << "time out!" << std::endl; std::cout << "time out!" << std::endl;
go[&]() -> future_t<> 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; std::cout << "all event signal!" << std::endl;
else else
std::cout << "time out!" << std::endl; std::cout << "time out!" << std::endl;
go[&]() -> future_t<> 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; std::cout << "all event signal!" << std::endl;
else else
std::cout << "time out!" << std::endl; std::cout << "time out!" << std::endl;

+ 4
- 2
tutorial/test_async_event_timeout.cpp View File

intptr_t counter = 0; intptr_t counter = 0;
for (;;) for (;;)
{ {
if (co_await evt.wait_for(100ms))
auto result = co_await evt.wait_for(100ms);
if (result)
break; break;
++counter; ++counter;
std::cout << "."; std::cout << ".";
intptr_t counter = 0; intptr_t counter = 0;
for (;;) 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 << counter << std::endl;
std::cout << "all event signal!" << std::endl; std::cout << "all event signal!" << std::endl;

+ 4
- 2
tutorial/test_async_event_v2.cpp View File



static future_t<> resumable_wait_event(event_v2::event_t e, int idx) 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; std::cout << "[" << idx << "]event signal!" << std::endl;
else else
std::cout << "[" << idx << "]time out!" << std::endl; std::cout << "[" << idx << "]time out!" << std::endl;


static future_t<> resumable_wait_timeout(event_v2::event_t e, milliseconds dt, 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; std::cout << "[" << idx << "]event signal!" << std::endl;
else else
std::cout << "[" << idx << "]time out!" << std::endl; std::cout << "[" << idx << "]time out!" << std::endl;

+ 6
- 6
tutorial/test_async_memory_layout.cpp View File

using promise_type = typename future_type::promise_type; using promise_type = typename future_type::promise_type;
using state_type = typename future_type::state_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); auto handler = coroutine_handle<promise_type>::from_address(frame_ptr);
promise_type* promise = &handler.promise(); promise_type* promise = &handler.promise();
state_type* state = handler.promise().get_state(); state_type* state = handler.promise().get_state();
std::cout << " future size=" << sizeof(future_type) << " / " << _Align_size<future_type>() << std::endl; 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 << " 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 << " 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 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 << " promise ptr=" << promise << "," << (void*)&promise << std::endl;
std::cout << " handle ptr=" << handler.address() << "," << (void*)&handler << std::endl; std::cout << " handle ptr=" << handler.address() << "," << (void*)&handler << std::endl;
std::cout << " state ptr=" << state << "," << (void*)&state << std::endl; std::cout << " state ptr=" << state << "," << (void*)&state << std::endl;
using promise_type = typename future_type::promise_type; using promise_type = typename future_type::promise_type;
using state_type = typename future_type::state_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); auto handler = coroutine_handle<promise_type>::from_address(frame_ptr);
promise_type * promise = &handler.promise(); promise_type * promise = &handler.promise();
state_type * state = handler.promise().get_state(); state_type * state = handler.promise().get_state();
std::cout << " future size=" << sizeof(future_type) << " / " << _Align_size<future_type>() << std::endl; 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 << " 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 << " 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 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 << " promise ptr=" << promise << "," << (void *)&promise << std::endl;
std::cout << " handle ptr=" << handler.address() << "," << (void*)&handler << std::endl; std::cout << " handle ptr=" << handler.address() << "," << (void*)&handler << std::endl;
std::cout << " state ptr=" << state << "," << (void*)&state << std::endl; std::cout << " state ptr=" << state << "," << (void*)&state << std::endl;

+ 10
- 2
tutorial/test_async_mutex.cpp View File

for (size_t i = 0; i < N; ++i) 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(); co_await yield();
}
++g_counter; ++g_counter;
std::cout << "push:" << g_counter << " on " << idx << std::endl; std::cout << "push:" << g_counter << " on " << idx << std::endl;
for (size_t i = 0; i < N; ++i) 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(); co_await yield();
}
++g_counter; ++g_counter;
std::cout << "push:" << g_counter << " on " << idx << std::endl; std::cout << "push:" << g_counter << " on " << idx << std::endl;

+ 4
- 4
tutorial/test_async_routine.cpp View File

{ {
co_await resumef::sleep_for(100ms); co_await resumef::sleep_for(100ms);
std::cout << "timer after 100ms" << std::endl; 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;
} }
} }
std::cout << "test_routine_use_timer_2" << std::endl; std::cout << "test_routine_use_timer_2" << std::endl;
co_await test_routine_use_timer(); 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(); 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(); 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() void resumable_main_routine()

+ 2
- 1
tutorial/test_async_sleep.cpp View File

go[&]() -> future_t<> 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; std::cout << "all event signal!" << std::endl;
else else
std::cout << "time out!" << std::endl; std::cout << "time out!" << std::endl;

+ 17
- 1
tutorial/test_async_switch_scheduler.cpp View File

(void)c_done.write(true); (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() void resumable_main_switch_scheduler()
{ {
sch_in_main = this_scheduler(); sch_in_main = this_scheduler();
channel_t<bool> c_done{ 1 }; channel_t<bool> c_done{ 1 };
std::thread other(&run_in_thread, std::ref(c_done)); 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<> go[&other, c_done]()->future_t<>
{ {
co_await c_done; //第一次等待,等待run_in_thread准备好了 co_await c_done; //第一次等待,等待run_in_thread准备好了
go resumable_get_long_switch_scheduler(1, c_done); //开启另外一个协程 go resumable_get_long_switch_scheduler(1, c_done); //开启另外一个协程
//co_await resumable_get_long(3, c_done); //co_await resumable_get_long(3, c_done);
co_await 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(); sch_in_main->run_until_notask();



Loading…
Cancel
Save