@@ -12,7 +12,9 @@ elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") | |||
endif() | |||
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() | |||
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") | |||
@@ -112,4 +114,9 @@ ${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}) | |||
if (UNIX) | |||
target_link_libraries(rf_tutorial ${LIB_NAME} mimalloc) | |||
else() | |||
target_link_libraries(rf_tutorial ${LIB_NAME}) | |||
endif() |
@@ -24,4 +24,8 @@ | |||
/* #undef _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 */ |
@@ -15,3 +15,19 @@ | |||
#define current_scheduler() (co_await ::resumef::get_current_scheduler()) | |||
#define root_state() (co_await ::resumef::get_root_state()) | |||
#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 |
@@ -113,24 +113,6 @@ namespace resumef | |||
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) | |||
{ | |||
#if !RESUMEF_DISABLE_MULT_THREAD | |||
@@ -149,28 +131,6 @@ namespace resumef | |||
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_() | |||
{ | |||
@@ -195,7 +155,7 @@ namespace resumef | |||
#if !RESUMEF_DISABLE_MULT_THREAD | |||
scoped_lock<spinlock> __guard(_lock_running); | |||
#endif | |||
if (_runing_states.empty()) | |||
if (likely(_runing_states.empty())) | |||
return false; | |||
std::swap(_cached_states, _runing_states); | |||
@@ -215,15 +175,15 @@ namespace resumef | |||
//介于网上有人做评测,导致单协程切换数据很难看,那就注释掉吧。 | |||
//std::this_thread::yield(); | |||
if (this->run_one_batch()) continue; //当前运行了一个state,则认为还可能有任务未完成 | |||
if (likely(this->run_one_batch())) continue; //当前运行了一个state,则认为还可能有任务未完成 | |||
{ | |||
#if !RESUMEF_DISABLE_MULT_THREAD | |||
scoped_lock<spinlock> __guard(_lock_ready); | |||
#endif | |||
if (!_ready_task.empty()) continue; //当前还存在task,则必然还有任务未完成 | |||
if (likely(!_ready_task.empty())) continue; //当前还存在task,则必然还有任务未完成 | |||
} | |||
if (!_timer->empty()) continue; //定时器不为空,也需要等待定时器触发 | |||
if (unlikely(!_timer->empty())) continue; //定时器不为空,也需要等待定时器触发 | |||
break; | |||
}; |
@@ -146,4 +146,44 @@ namespace resumef | |||
private: | |||
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; | |||
} | |||
} |
@@ -57,10 +57,14 @@ namespace resumef | |||
void state_generator_t::resume() | |||
{ | |||
if (_coro) | |||
if (likely(_coro)) | |||
{ | |||
_coro.resume(); | |||
if (_coro.done()) | |||
if (likely(!_coro.done())) | |||
{ | |||
_scheduler->add_generator(this); | |||
} | |||
else | |||
{ | |||
coroutine_handle<> handler = _coro; | |||
_coro = nullptr; | |||
@@ -68,10 +72,6 @@ namespace resumef | |||
handler.destroy(); | |||
} | |||
else | |||
{ | |||
_scheduler->add_generator(this); | |||
} | |||
} | |||
} | |||
@@ -25,9 +25,13 @@ namespace resumef | |||
void timer_manager::clear() | |||
{ | |||
#if !RESUMEF_DISABLE_MULT_THREAD | |||
std::unique_lock<spinlock> __lock(_added_mtx); | |||
#endif | |||
auto _atimer = std::move(_added_timers); | |||
#if !RESUMEF_DISABLE_MULT_THREAD | |||
__lock.unlock(); | |||
#endif | |||
for (auto& sptr : _atimer) | |||
call_target_(sptr, true); | |||
@@ -42,7 +46,9 @@ namespace resumef | |||
assert(sptr); | |||
assert(sptr->st == timer_target::State::Invalid); | |||
#if !RESUMEF_DISABLE_MULT_THREAD | |||
scoped_lock<spinlock> __lock(_added_mtx); | |||
#endif | |||
#if _DEBUG | |||
assert(sptr->_manager == nullptr); | |||
sptr->_manager = this; | |||
@@ -69,13 +75,17 @@ namespace resumef | |||
void timer_manager::update() | |||
{ | |||
{ | |||
#if !RESUMEF_DISABLE_MULT_THREAD | |||
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); | |||
_added_timers.reserve(128); | |||
#if !RESUMEF_DISABLE_MULT_THREAD | |||
__lock.unlock(); | |||
#endif | |||
for (auto& sptr : _atimer) | |||
{ | |||
@@ -93,7 +103,7 @@ namespace resumef | |||
} | |||
} | |||
if (_runing_timers.size() > 0) | |||
if (unlikely(_runing_timers.size() > 0)) | |||
{ | |||
auto now_ = clock_type::now(); | |||
@@ -139,7 +139,9 @@ namespace resumef | |||
return add_(std::make_shared<timer_target>(tp_, std::forward<_Cb>(cb_))); | |||
} | |||
private: | |||
#if !RESUMEF_DISABLE_MULT_THREAD | |||
spinlock _added_mtx; | |||
#endif | |||
timer_vector_type _added_timers; | |||
timer_map_type _runing_timers; | |||
@@ -166,13 +166,13 @@ | |||
</SDLCheck> | |||
<EnablePREfast>true</EnablePREfast> | |||
<InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion> | |||
<OmitFramePointers>true</OmitFramePointers> | |||
<BufferSecurityCheck>false</BufferSecurityCheck> | |||
<EnableParallelCodeGeneration>true</EnableParallelCodeGeneration> | |||
<DisableSpecificWarnings>4834;4505</DisableSpecificWarnings> | |||
<FunctionLevelLinking>true</FunctionLevelLinking> | |||
<RuntimeTypeInfo>true</RuntimeTypeInfo> | |||
<ExceptionHandling>Async</ExceptionHandling> | |||
<EnableFiberSafeOptimizations>true</EnableFiberSafeOptimizations> | |||
</ClCompile> | |||
<Link> | |||
<SubSystem>Console</SubSystem> | |||
@@ -180,8 +180,7 @@ | |||
<OptimizeReferences>true</OptimizeReferences> | |||
<GenerateDebugInformation>true</GenerateDebugInformation> | |||
<LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration> | |||
<Profile> | |||
</Profile> | |||
<Profile>true</Profile> | |||
</Link> | |||
</ItemDefinitionGroup> | |||
<ItemGroup> |