endif() | endif() | ||||
if (UNIX) | if (UNIX) | ||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread") | |||||
find_package(mimalloc 1.4 REQUIRED) | |||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC -pthread") | |||||
endif() | endif() | ||||
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") | if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") | ||||
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/bin) | set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/bin) | ||||
add_executable(rf_tutorial ${TSRC}) | add_executable(rf_tutorial ${TSRC}) | ||||
target_link_libraries(rf_tutorial ${LIB_NAME}) | |||||
if (UNIX) | |||||
target_link_libraries(rf_tutorial ${LIB_NAME} mimalloc) | |||||
else() | |||||
target_link_libraries(rf_tutorial ${LIB_NAME}) | |||||
endif() |
/* #undef _WITH_LOCK_FREE_Q_KEEP_REAL_SIZE */ | /* #undef _WITH_LOCK_FREE_Q_KEEP_REAL_SIZE */ | ||||
#endif //_WITH_LOCK_FREE_Q_KEEP_REAL_SIZE | #endif //_WITH_LOCK_FREE_Q_KEEP_REAL_SIZE | ||||
#ifndef RESUMEF_DISABLE_MULT_THREAD | |||||
/* #undef RESUMEF_DISABLE_MULT_THREAD */ | |||||
#endif //RESUMEF_DISABLE_MULT_THREAD | |||||
/* #undef RESUMEF_USE_CUSTOM_SPINLOCK */ | /* #undef RESUMEF_USE_CUSTOM_SPINLOCK */ |
#define current_scheduler() (co_await ::resumef::get_current_scheduler()) | #define current_scheduler() (co_await ::resumef::get_current_scheduler()) | ||||
#define root_state() (co_await ::resumef::get_root_state()) | #define root_state() (co_await ::resumef::get_root_state()) | ||||
#define current_task() (co_await ::resumef::get_current_task()) | #define current_task() (co_await ::resumef::get_current_task()) | ||||
#ifdef _MSC_VER | |||||
#ifndef likely | |||||
#define likely(x) x | |||||
#endif // likely | |||||
#ifndef unlikely | |||||
#define unlikely(x) x | |||||
#endif // unlikely | |||||
#else // _MSC_VER | |||||
#ifndef likely | |||||
#define likely(x) __builtin_expect(!!(x), 1) | |||||
#endif // likely | |||||
#ifndef unlikely | |||||
#define unlikely(x) __builtin_expect(!!(x), 0) | |||||
#endif // unlikely | |||||
#endif // _MSC_VER |
return task; | return task; | ||||
} | } | ||||
void scheduler_t::add_generator(state_base_t* sptr) | |||||
{ | |||||
assert(sptr != nullptr); | |||||
#if !RESUMEF_DISABLE_MULT_THREAD | |||||
scoped_lock<spinlock> __guard(_lock_running); | |||||
#endif | |||||
_runing_states.emplace_back(sptr); | |||||
} | |||||
void scheduler_t::del_final(state_base_t* sptr) | |||||
{ | |||||
#if !RESUMEF_DISABLE_MULT_THREAD | |||||
scoped_lock<spinlock> __guard(_lock_ready); | |||||
#endif | |||||
this->_ready_task.erase(sptr); | |||||
} | |||||
std::unique_ptr<task_t> scheduler_t::del_switch(state_base_t* sptr) | std::unique_ptr<task_t> scheduler_t::del_switch(state_base_t* sptr) | ||||
{ | { | ||||
#if !RESUMEF_DISABLE_MULT_THREAD | #if !RESUMEF_DISABLE_MULT_THREAD | ||||
return task_ptr; | return task_ptr; | ||||
} | } | ||||
void scheduler_t::add_switch(std::unique_ptr<task_t> task) | |||||
{ | |||||
state_base_t* sptr = task->_state.get(); | |||||
#if !RESUMEF_DISABLE_MULT_THREAD | |||||
scoped_lock<spinlock> __guard(_lock_ready); | |||||
#endif | |||||
this->_ready_task.emplace(sptr, std::move(task)); | |||||
} | |||||
task_t* scheduler_t::find_task(state_base_t* sptr) const noexcept | |||||
{ | |||||
#if !RESUMEF_DISABLE_MULT_THREAD | |||||
scoped_lock<spinlock> __guard(_lock_ready); | |||||
#endif | |||||
auto iter = this->_ready_task.find(sptr); | |||||
if (iter != this->_ready_task.end()) | |||||
return iter->second.get(); | |||||
return nullptr; | |||||
} | |||||
/* | /* | ||||
void scheduler_t::cancel_all_task_() | void scheduler_t::cancel_all_task_() | ||||
{ | { | ||||
#if !RESUMEF_DISABLE_MULT_THREAD | #if !RESUMEF_DISABLE_MULT_THREAD | ||||
scoped_lock<spinlock> __guard(_lock_running); | scoped_lock<spinlock> __guard(_lock_running); | ||||
#endif | #endif | ||||
if (_runing_states.empty()) | |||||
if (likely(_runing_states.empty())) | |||||
return false; | return false; | ||||
std::swap(_cached_states, _runing_states); | std::swap(_cached_states, _runing_states); | ||||
//介于网上有人做评测,导致单协程切换数据很难看,那就注释掉吧。 | //介于网上有人做评测,导致单协程切换数据很难看,那就注释掉吧。 | ||||
//std::this_thread::yield(); | //std::this_thread::yield(); | ||||
if (this->run_one_batch()) continue; //当前运行了一个state,则认为还可能有任务未完成 | |||||
if (likely(this->run_one_batch())) continue; //当前运行了一个state,则认为还可能有任务未完成 | |||||
{ | { | ||||
#if !RESUMEF_DISABLE_MULT_THREAD | #if !RESUMEF_DISABLE_MULT_THREAD | ||||
scoped_lock<spinlock> __guard(_lock_ready); | scoped_lock<spinlock> __guard(_lock_ready); | ||||
#endif | #endif | ||||
if (!_ready_task.empty()) continue; //当前还存在task,则必然还有任务未完成 | |||||
if (likely(!_ready_task.empty())) continue; //当前还存在task,则必然还有任务未完成 | |||||
} | } | ||||
if (!_timer->empty()) continue; //定时器不为空,也需要等待定时器触发 | |||||
if (unlikely(!_timer->empty())) continue; //定时器不为空,也需要等待定时器触发 | |||||
break; | break; | ||||
}; | }; |
private: | private: | ||||
scheduler_t* _scheduler_ptr; | scheduler_t* _scheduler_ptr; | ||||
}; | }; | ||||
inline void scheduler_t::add_generator(state_base_t* sptr) | |||||
{ | |||||
assert(sptr != nullptr); | |||||
#if !RESUMEF_DISABLE_MULT_THREAD | |||||
scoped_lock<spinlock> __guard(_lock_running); | |||||
#endif | |||||
_runing_states.emplace_back(sptr); | |||||
} | |||||
inline void scheduler_t::del_final(state_base_t* sptr) | |||||
{ | |||||
#if !RESUMEF_DISABLE_MULT_THREAD | |||||
scoped_lock<spinlock> __guard(_lock_ready); | |||||
#endif | |||||
this->_ready_task.erase(sptr); | |||||
} | |||||
inline void scheduler_t::add_switch(std::unique_ptr<task_t> task) | |||||
{ | |||||
state_base_t* sptr = task->_state.get(); | |||||
#if !RESUMEF_DISABLE_MULT_THREAD | |||||
scoped_lock<spinlock> __guard(_lock_ready); | |||||
#endif | |||||
this->_ready_task.emplace(sptr, std::move(task)); | |||||
} | |||||
inline task_t* scheduler_t::find_task(state_base_t* sptr) const noexcept | |||||
{ | |||||
#if !RESUMEF_DISABLE_MULT_THREAD | |||||
scoped_lock<spinlock> __guard(_lock_ready); | |||||
#endif | |||||
auto iter = this->_ready_task.find(sptr); | |||||
if (iter != this->_ready_task.end()) | |||||
return iter->second.get(); | |||||
return nullptr; | |||||
} | |||||
} | } |
void state_generator_t::resume() | void state_generator_t::resume() | ||||
{ | { | ||||
if (_coro) | |||||
if (likely(_coro)) | |||||
{ | { | ||||
_coro.resume(); | _coro.resume(); | ||||
if (_coro.done()) | |||||
if (likely(!_coro.done())) | |||||
{ | |||||
_scheduler->add_generator(this); | |||||
} | |||||
else | |||||
{ | { | ||||
coroutine_handle<> handler = _coro; | coroutine_handle<> handler = _coro; | ||||
_coro = nullptr; | _coro = nullptr; | ||||
handler.destroy(); | handler.destroy(); | ||||
} | } | ||||
else | |||||
{ | |||||
_scheduler->add_generator(this); | |||||
} | |||||
} | } | ||||
} | } | ||||
void timer_manager::clear() | void timer_manager::clear() | ||||
{ | { | ||||
#if !RESUMEF_DISABLE_MULT_THREAD | |||||
std::unique_lock<spinlock> __lock(_added_mtx); | std::unique_lock<spinlock> __lock(_added_mtx); | ||||
#endif | |||||
auto _atimer = std::move(_added_timers); | auto _atimer = std::move(_added_timers); | ||||
#if !RESUMEF_DISABLE_MULT_THREAD | |||||
__lock.unlock(); | __lock.unlock(); | ||||
#endif | |||||
for (auto& sptr : _atimer) | for (auto& sptr : _atimer) | ||||
call_target_(sptr, true); | call_target_(sptr, true); | ||||
assert(sptr); | assert(sptr); | ||||
assert(sptr->st == timer_target::State::Invalid); | assert(sptr->st == timer_target::State::Invalid); | ||||
#if !RESUMEF_DISABLE_MULT_THREAD | |||||
scoped_lock<spinlock> __lock(_added_mtx); | scoped_lock<spinlock> __lock(_added_mtx); | ||||
#endif | |||||
#if _DEBUG | #if _DEBUG | ||||
assert(sptr->_manager == nullptr); | assert(sptr->_manager == nullptr); | ||||
sptr->_manager = this; | sptr->_manager = this; | ||||
void timer_manager::update() | void timer_manager::update() | ||||
{ | { | ||||
{ | { | ||||
#if !RESUMEF_DISABLE_MULT_THREAD | |||||
std::unique_lock<spinlock> __lock(_added_mtx); | std::unique_lock<spinlock> __lock(_added_mtx); | ||||
#endif | |||||
if (_added_timers.size() > 0) | |||||
if (unlikely(_added_timers.size() > 0)) | |||||
{ | { | ||||
auto _atimer = std::move(_added_timers); | auto _atimer = std::move(_added_timers); | ||||
_added_timers.reserve(128); | _added_timers.reserve(128); | ||||
#if !RESUMEF_DISABLE_MULT_THREAD | |||||
__lock.unlock(); | __lock.unlock(); | ||||
#endif | |||||
for (auto& sptr : _atimer) | for (auto& sptr : _atimer) | ||||
{ | { | ||||
} | } | ||||
} | } | ||||
if (_runing_timers.size() > 0) | |||||
if (unlikely(_runing_timers.size() > 0)) | |||||
{ | { | ||||
auto now_ = clock_type::now(); | auto now_ = clock_type::now(); | ||||
return add_(std::make_shared<timer_target>(tp_, std::forward<_Cb>(cb_))); | return add_(std::make_shared<timer_target>(tp_, std::forward<_Cb>(cb_))); | ||||
} | } | ||||
private: | private: | ||||
#if !RESUMEF_DISABLE_MULT_THREAD | |||||
spinlock _added_mtx; | spinlock _added_mtx; | ||||
#endif | |||||
timer_vector_type _added_timers; | timer_vector_type _added_timers; | ||||
timer_map_type _runing_timers; | timer_map_type _runing_timers; | ||||
</SDLCheck> | </SDLCheck> | ||||
<EnablePREfast>true</EnablePREfast> | <EnablePREfast>true</EnablePREfast> | ||||
<InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion> | <InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion> | ||||
<OmitFramePointers>true</OmitFramePointers> | |||||
<BufferSecurityCheck>false</BufferSecurityCheck> | <BufferSecurityCheck>false</BufferSecurityCheck> | ||||
<EnableParallelCodeGeneration>true</EnableParallelCodeGeneration> | <EnableParallelCodeGeneration>true</EnableParallelCodeGeneration> | ||||
<DisableSpecificWarnings>4834;4505</DisableSpecificWarnings> | <DisableSpecificWarnings>4834;4505</DisableSpecificWarnings> | ||||
<FunctionLevelLinking>true</FunctionLevelLinking> | <FunctionLevelLinking>true</FunctionLevelLinking> | ||||
<RuntimeTypeInfo>true</RuntimeTypeInfo> | <RuntimeTypeInfo>true</RuntimeTypeInfo> | ||||
<ExceptionHandling>Async</ExceptionHandling> | <ExceptionHandling>Async</ExceptionHandling> | ||||
<EnableFiberSafeOptimizations>true</EnableFiberSafeOptimizations> | |||||
</ClCompile> | </ClCompile> | ||||
<Link> | <Link> | ||||
<SubSystem>Console</SubSystem> | <SubSystem>Console</SubSystem> | ||||
<OptimizeReferences>true</OptimizeReferences> | <OptimizeReferences>true</OptimizeReferences> | ||||
<GenerateDebugInformation>true</GenerateDebugInformation> | <GenerateDebugInformation>true</GenerateDebugInformation> | ||||
<LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration> | <LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration> | ||||
<Profile> | |||||
</Profile> | |||||
<Profile>true</Profile> | |||||
</Link> | </Link> | ||||
</ItemDefinitionGroup> | </ItemDefinitionGroup> | ||||
<ItemGroup> | <ItemGroup> |