bin | bin | ||||
out | out | ||||
/CMakeSettings.json | /CMakeSettings.json | ||||
install | |||||
lib |
option(OPT_KEEP_REAL_SIZE "Keep real size in queue" OFF) | option(OPT_KEEP_REAL_SIZE "Keep real size in queue" OFF) | ||||
option(OPT_DISABLE_MULT_THREAD "Disable multi-threaded scheduler" OFF) | option(OPT_DISABLE_MULT_THREAD "Disable multi-threaded scheduler" OFF) | ||||
option(OPT_USE_MIMALLOC "Use mimalloc" OFF) | option(OPT_USE_MIMALLOC "Use mimalloc" OFF) | ||||
option(OPT_DYNAMIC_LIBRARY "Use shared library" OFF) | |||||
option(OPT_DYNAMIC_LIBRARY "Use shared library" ON) | |||||
option(CMAKE_ENABLE_UNIT_TEST "Enable unit test" OFF) | |||||
if (UNIX) | if (UNIX) | ||||
if(OPT_USE_MIMALLOC) | if(OPT_USE_MIMALLOC) | ||||
if(OPT_DISABLE_MULT_THREAD) | if(OPT_DISABLE_MULT_THREAD) | ||||
set(RESUMEF_DISABLE_MULT_THREAD 1) | set(RESUMEF_DISABLE_MULT_THREAD 1) | ||||
endif() | endif() | ||||
if(OPT_DYNAMIC_LIBRARY) | |||||
set(RESUMEF_USE_SHARD_LIBRARY 1) | |||||
add_compile_definitions("-DRESUMEF_DYNAMIC_EXPORTS=1") | |||||
endif() | |||||
configure_file( | configure_file( | ||||
${CMAKE_SOURCE_DIR}/config.h.in | ${CMAKE_SOURCE_DIR}/config.h.in | ||||
file(GLOB_RECURSE SOURCE_FILES ${CMAKE_SOURCE_DIR}/source/*.*) | file(GLOB_RECURSE SOURCE_FILES ${CMAKE_SOURCE_DIR}/source/*.*) | ||||
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/lib) | set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/lib) | ||||
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/lib) | |||||
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/bin) | set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/bin) | ||||
if(OPT_DYNAMIC_LIBRARY) | if(OPT_DYNAMIC_LIBRARY) | ||||
${HEADER_FILES} | ${HEADER_FILES} | ||||
${SOURCE_FILES} | ${SOURCE_FILES} | ||||
) | ) | ||||
target_compile_definitions(${PROJECT_NAME} | |||||
PRIVATE LIBRF_DYNAMIC_EXPORTS=1 | |||||
) | |||||
else() | else() | ||||
add_library(${PROJECT_NAME} STATIC | add_library(${PROJECT_NAME} STATIC | ||||
${HEADER_FILES} | ${HEADER_FILES} | ||||
${SOURCE_FILES} | ${SOURCE_FILES} | ||||
) | ) | ||||
target_compile_definitions(${PROJECT_NAME} | |||||
PRIVATE LIBRF_USE_STATIC_LIBRARY=1 | |||||
) | |||||
endif() | endif() | ||||
target_include_directories(${PROJECT_NAME} | target_include_directories(${PROJECT_NAME} | ||||
PUBLIC | PUBLIC | ||||
${CMAKE_CURRENT_SOURCE_DIR}/include | ${CMAKE_CURRENT_SOURCE_DIR}/include | ||||
) | ) | ||||
include_directories( | |||||
${CMAKE_SOURCE_DIR}/modern_cb | |||||
) | |||||
if(OPT_USE_MIMALLOC) | if(OPT_USE_MIMALLOC) | ||||
set(LIB_MIMALLOC, "mimalloc") | set(LIB_MIMALLOC, "mimalloc") | ||||
else() | else() | ||||
set(LIB_MIMALLOC, "") | set(LIB_MIMALLOC, "") | ||||
endif() | endif() | ||||
add_subdirectory(tutorial) | |||||
#add_subdirectory(benchmark) | |||||
if(CMAKE_ENABLE_UNIT_TEST) | |||||
include_directories( | |||||
${CMAKE_SOURCE_DIR}/modern_cb | |||||
) | |||||
add_subdirectory(tutorial) | |||||
#add_subdirectory(benchmark) | |||||
endif() | |||||
include(${CMAKE_SOURCE_DIR}/cmake/install.cmake) | |||||
install(DIRECTORY ${CMAKE_SOURCE_DIR}/include/librf DESTINATION include) |
include(${CMAKE_CURRENT_LIST_DIR}/SelectDynamicLibrary.cmake) | |||||
select_dynamic_library(librf librf/librf.h) |
include(SelectLibraryConfigurations) | |||||
macro(_acl_copy_dynamic_library_build_type basename build_type) | |||||
if(${build_type} STREQUAL "Debug") | |||||
set(_acl_build_type_dir "Debug") | |||||
set(_acl_runtime_output_dir ${CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG}) | |||||
elseif(${build_type} STREQUAL "Release") | |||||
set(_acl_build_type_dir "Release") | |||||
set(_acl_runtime_output_dir ${CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE}) | |||||
elseif(${build_type} STREQUAL "MinSizeRel") | |||||
set(_acl_build_type_dir "Release") | |||||
set(_acl_runtime_output_dir ${CMAKE_RUNTIME_OUTPUT_DIRECTORY_MINSIZEREL}) | |||||
elseif(${build_type} STREQUAL "RelWithDebInfo") | |||||
set(_acl_build_type_dir "Release") | |||||
set(_acl_runtime_output_dir ${CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELWITHDEBINFO}) | |||||
endif() | |||||
#message(STATUS "_acl_build_type_dir=${CMAKE_CURRENT_LIST_DIR}/../lib/${CMAKE_CXX_PLATFORM_ID}/${CMAKE_CXX_COMPILER_ARCHITECTURE_ID}-${_acl_build_type_dir}") | |||||
#message(STATUS "_acl_runtime_output_dir=${_acl_runtime_output_dir}") | |||||
find_file(_acl_${basename}_dynamic_binary | |||||
NAMES "Acl.${basename}.dll" "Acl.${basename}.so" | |||||
PATHS | |||||
${CMAKE_CURRENT_LIST_DIR}/../bin/${CMAKE_CXX_PLATFORM_ID}/${CMAKE_CXX_COMPILER_ARCHITECTURE_ID}-${_acl_build_type_dir} | |||||
NO_DEFAULT_PATH | |||||
) | |||||
if(NOT _acl_${basename}_dynamic_binary) | |||||
find_file(_acl_${basename}_dynamic_binary | |||||
NAMES "${basename}.dll" "${basename}.so" | |||||
PATHS | |||||
${CMAKE_CURRENT_LIST_DIR}/../bin/${CMAKE_CXX_PLATFORM_ID}/${CMAKE_CXX_COMPILER_ARCHITECTURE_ID}-${_acl_build_type_dir} | |||||
NO_DEFAULT_PATH | |||||
) | |||||
endif() | |||||
#message(STATUS "_acl_runtime_dynamic_binary=${_acl_runtime_dynamic_binary}") | |||||
if(_acl_${basename}_dynamic_binary) | |||||
file(INSTALL ${_acl_${basename}_dynamic_binary} DESTINATION ${_acl_runtime_output_dir}) | |||||
endif() | |||||
unset(_acl_build_type_dir) | |||||
unset(_acl_runtime_output_dir) | |||||
unset(_acl_${basename}_dynamic_binary CACHE) | |||||
endmacro(_acl_copy_dynamic_library_build_type) | |||||
macro(_acl_copy_dynamic_library basename) | |||||
if(DEFINED CMAKE_CONFIGURATION_TYPES) | |||||
foreach(build_type ${CMAKE_CONFIGURATION_TYPES}) | |||||
_acl_copy_dynamic_library_build_type(${basename} ${build_type}) | |||||
endforeach(build_type) | |||||
elseif(DEFINED CMAKE_BUILD_TYPE) | |||||
_acl_copy_dynamic_library_build_type(${basename} ${CMAKE_BUILD_TYPE}) | |||||
else() | |||||
_acl_copy_dynamic_library_build_type(${basename} "Release") | |||||
endif() | |||||
endmacro(_acl_copy_dynamic_library) | |||||
macro(select_dynamic_library basename header) | |||||
#message(STATUS "basename=${basename}") | |||||
#message(STATUS "header=${header}") | |||||
# 如果已经找到了 basename 指定的模块,则只做拷贝运行时的动态库的工作 | |||||
#message(STATUS "${basename}_FOUND=${${basename}_FOUND}") | |||||
if(${basename}_FOUND) | |||||
_acl_copy_dynamic_library(${basename}) | |||||
return() | |||||
endif() | |||||
# 查找头文件所在的路径 | |||||
find_path(${basename}_INCLUDE_DIR ${header} | |||||
${CMAKE_CURRENT_LIST_DIR}/../include | |||||
NO_DEFAULT_PATH | |||||
) | |||||
# 查找调试版本的库文件所在路径 | |||||
find_library("${basename}_LIBRARY_DEBUG" | |||||
NAMES "Acl.${basename}" | |||||
PATHS | |||||
${CMAKE_CURRENT_LIST_DIR}/../lib/${CMAKE_CXX_PLATFORM_ID}/${CMAKE_CXX_COMPILER_ARCHITECTURE_ID}-Debug | |||||
NO_DEFAULT_PATH | |||||
) | |||||
if(NOT ${basename}_LIBRARY_DEBUG) | |||||
find_library("${basename}_LIBRARY_DEBUG" | |||||
NAMES "${basename}" | |||||
PATHS | |||||
${CMAKE_CURRENT_LIST_DIR}/../lib/${CMAKE_CXX_PLATFORM_ID}/${CMAKE_CXX_COMPILER_ARCHITECTURE_ID}-Debug | |||||
NO_DEFAULT_PATH | |||||
) | |||||
endif() | |||||
# 查找发行版本的库文件所在路径 | |||||
find_library("${basename}_LIBRARY_RELEASE" | |||||
NAMES "Acl.${basename}" | |||||
PATHS | |||||
${CMAKE_CURRENT_LIST_DIR}/../lib/${CMAKE_CXX_PLATFORM_ID}/${CMAKE_CXX_COMPILER_ARCHITECTURE_ID}-Release | |||||
NO_DEFAULT_PATH | |||||
) | |||||
if(NOT ${basename}_LIBRARY_RELEASE) | |||||
find_library("${basename}_LIBRARY_RELEASE" | |||||
NAMES "${basename}" | |||||
PATHS | |||||
${CMAKE_CURRENT_LIST_DIR}/../lib/${CMAKE_CXX_PLATFORM_ID}/${CMAKE_CXX_COMPILER_ARCHITECTURE_ID}-Release | |||||
NO_DEFAULT_PATH | |||||
) | |||||
endif() | |||||
# 使用cmake内置的 select_library_configurations 函数生成 ${basename}_LIBRARY 字段 | |||||
select_library_configurations(${basename}) | |||||
set(${basename}_FOUND FALSE) | |||||
if(${basename}_LIBRARY AND ${basename}_INCLUDE_DIR) | |||||
set(${basename}_FOUND TRUE) | |||||
if(NOT ${basename}_DIR) | |||||
set(${basename}_DIR ${CMAKE_CURRENT_LIST_DIR}) | |||||
endif() | |||||
# 做拷贝运行时的动态库到目标目录 | |||||
_acl_copy_dynamic_library(${basename}) | |||||
# 创建 basename 指定的导入接口模块 | |||||
if(NOT TARGET Acl::${basename}) | |||||
add_library(Acl::${basename} UNKNOWN IMPORTED) | |||||
set_target_properties(Acl::${basename} PROPERTIES | |||||
INTERFACE_INCLUDE_DIRECTORIES "${${basename}_INCLUDE_DIR}") | |||||
set_property(TARGET Acl::${basename} APPEND PROPERTY | |||||
IMPORTED_CONFIGURATIONS RELEASE) | |||||
set_target_properties(Acl::${basename} PROPERTIES | |||||
IMPORTED_LOCATION_RELEASE "${${basename}_LIBRARY_RELEASE}") | |||||
set_property(TARGET Acl::${basename} APPEND PROPERTY | |||||
IMPORTED_CONFIGURATIONS DEBUG) | |||||
set_target_properties(Acl::${basename} PROPERTIES | |||||
IMPORTED_LOCATION_DEBUG "${${basename}_LIBRARY_DEBUG}") | |||||
endif() | |||||
endif() | |||||
mark_as_advanced(${basename}_DIR) | |||||
mark_as_advanced(${basename}_LIBRARY) | |||||
mark_as_advanced(${basename}_INCLUDE_DIR) | |||||
#message(STATUS "${basename}_DIR=${${basename}_DIR}") | |||||
#message(STATUS "${basename}_LIBRARY=${${basename}_LIBRARY}") | |||||
#message(STATUS "${basename}_LIBRARY_DEBUG=${${basename}_LIBRARY_DEBUG}") | |||||
#message(STATUS "${basename}_LIBRARY_RELEASE=${${basename}_LIBRARY_RELEASE}") | |||||
#message(STATUS "${basename}_INCLUDE_DIR=${${basename}_INCLUDE_DIR}") | |||||
endmacro(select_dynamic_library) |
| |||||
# Configuration | |||||
# Used by cmake to find_package(xxx) | |||||
set(PROJECT_CONFIG "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake") | |||||
# Add definitions for targets | |||||
# Values: | |||||
# * Debug: -Dxxx_DEBUG=1 | |||||
# * Release: -Dxxx_DEBUG=0 | |||||
# * other: -Dxxx_DEBUG=0 | |||||
target_compile_definitions(${PROJECT_NAME} PUBLIC ${PROJECT_NAME}_DEBUG=$<CONFIG:Debug>) | |||||
# Include module with function 'write_basic_package_version_file' | |||||
# Configure 'xxxConfigVersion.cmake' | |||||
include(CMakePackageConfigHelpers) | |||||
write_basic_package_version_file(${VERSION_CONFIG} VERSION ${PACKAGE_VERSION} | |||||
COMPATIBILITY SameMajorVersion) | |||||
# Configure 'xxxConfig.cmake' | |||||
configure_package_config_file(Config.cmake.in ${PROJECT_CONFIG} | |||||
INSTALL_DESTINATION cmake/${PROJECT_NAME}) | |||||
# Targets: | |||||
# * <prefix>/lib/Windows/x64-Debug/xxx.lib | |||||
# * <prefix>/bin/Windows/x64-Debug/xxx.dll | |||||
set(INSTALL_TARGET_PREFIX "${CMAKE_CXX_PLATFORM_ID}/${CMAKE_CXX_COMPILER_ARCHITECTURE_ID}") | |||||
install(TARGETS ${PROJECT_NAME} | |||||
CONFIGURATIONS Debug | |||||
LIBRARY DESTINATION "lib/${INSTALL_TARGET_PREFIX}-Debug" | |||||
ARCHIVE DESTINATION "lib/${INSTALL_TARGET_PREFIX}-Debug" | |||||
RUNTIME DESTINATION "bin/${INSTALL_TARGET_PREFIX}-Debug" | |||||
) | |||||
# * <prefix>/lib/Windows/x64-Release/xxx.lib | |||||
# * <prefix>/bin/Windows/x64-Release/xxx.dll | |||||
install(TARGETS ${PROJECT_NAME} | |||||
CONFIGURATIONS Release RelWithDebInfo MinSizeRel | |||||
LIBRARY DESTINATION "lib/${INSTALL_TARGET_PREFIX}-Release" | |||||
ARCHIVE DESTINATION "lib/${INSTALL_TARGET_PREFIX}-Release" | |||||
RUNTIME DESTINATION "bin/${INSTALL_TARGET_PREFIX}-Release" | |||||
) | |||||
# Config | |||||
# * <prefix>/cmake/xxxConfig.cmake | |||||
# * <prefix>/cmake/xxxConfigVersion.cmake | |||||
install(FILES ${PROJECT_CONFIG} DESTINATION cmake) |
#include "src/def.h" | #include "src/def.h" | ||||
#include "src/macro_def.inl" | #include "src/macro_def.inl" | ||||
#include "src/exception.inl" | |||||
#include "src/counted_ptr.h" | #include "src/counted_ptr.h" | ||||
#include "src/type_traits.inl" | #include "src/type_traits.inl" | ||||
#include "src/type_concept.inl" | #include "src/type_concept.inl" |
* @brief 版本号。 | * @brief 版本号。 | ||||
*/ | */ | ||||
constexpr size_t _Version = LIB_RESUMEF_VERSION; | constexpr size_t _Version = LIB_RESUMEF_VERSION; | ||||
/** | |||||
* @brief 获得当前线程下的调度器。 | |||||
*/ | |||||
scheduler_t* this_scheduler(); | |||||
} | } | ||||
#ifndef DOXYGEN_SKIP_PROPERTY | #ifndef DOXYGEN_SKIP_PROPERTY | ||||
} | } | ||||
} | } | ||||
#include "exception.inl" | |||||
#endif //DOXYGEN_SKIP_PROPERTY | #endif //DOXYGEN_SKIP_PROPERTY |
* @brief 构造一个事件。 | * @brief 构造一个事件。 | ||||
* @param initially 初始是否触发一次信号。 | * @param initially 初始是否触发一次信号。 | ||||
*/ | */ | ||||
event_t(bool initially = false); | |||||
LIBRF_API event_t(bool initially = false); | |||||
/** | /** | ||||
* @brief 构造一个无效的事件。 | * @brief 构造一个无效的事件。 | ||||
* @details 如果用于后续保存另外一个事件,则应当使用此构造函数,便于节省一次不必要的内部初始化。 | * @details 如果用于后续保存另外一个事件,则应当使用此构造函数,便于节省一次不必要的内部初始化。 | ||||
*/ | */ | ||||
event_t(std::adopt_lock_t); | |||||
LIBRF_API event_t(std::adopt_lock_t); | |||||
/** | /** | ||||
* @brief 采用shared_ptr<>来保存内部的事件实现。故不必担心正在被等待的协程,因为事件提前销毁而出现异常。 | * @brief 采用shared_ptr<>来保存内部的事件实现。故不必担心正在被等待的协程,因为事件提前销毁而出现异常。 | ||||
*/ | */ | ||||
~event_t(); | |||||
LIBRF_API ~event_t(); | |||||
/** | /** | ||||
* @brief 向所有正在等待的协程触发一次信号。 | * @brief 向所有正在等待的协程触发一次信号。 |
struct event_v2_impl : public std::enable_shared_from_this<event_v2_impl> | struct event_v2_impl : public std::enable_shared_from_this<event_v2_impl> | ||||
{ | { | ||||
event_v2_impl(bool initially) noexcept; | |||||
~event_v2_impl(); | |||||
LIBRF_API event_v2_impl(bool initially) noexcept; | |||||
LIBRF_API ~event_v2_impl(); | |||||
bool is_signaled() const noexcept | bool is_signaled() const noexcept | ||||
{ | { | ||||
{ | { | ||||
_counter.store(0, std::memory_order_release); | _counter.store(0, std::memory_order_release); | ||||
} | } | ||||
void signal_all() noexcept; | |||||
void signal() noexcept; | |||||
LIBRF_API void signal_all() noexcept; | |||||
LIBRF_API void signal() noexcept; | |||||
public: | public: | ||||
static constexpr bool USE_SPINLOCK = true; | static constexpr bool USE_SPINLOCK = true; | ||||
struct state_event_base_t : public state_base_t | struct state_event_base_t : public state_base_t | ||||
{ | { | ||||
virtual void resume() override; | |||||
virtual bool has_handler() const noexcept override; | |||||
LIBRF_API virtual void resume() override; | |||||
LIBRF_API virtual bool has_handler() const noexcept override; | |||||
virtual void on_cancel() noexcept = 0; | virtual void on_cancel() noexcept = 0; | ||||
virtual bool on_notify(event_v2_impl* eptr) = 0; | virtual bool on_notify(event_v2_impl* eptr) = 0; | ||||
: _value(&val) | : _value(&val) | ||||
{} | {} | ||||
virtual void on_cancel() noexcept override; | |||||
virtual bool on_notify(event_v2_impl* eptr) override; | |||||
virtual bool on_timeout() override; | |||||
LIBRF_API virtual void on_cancel() noexcept override; | |||||
LIBRF_API virtual bool on_notify(event_v2_impl* eptr) override; | |||||
LIBRF_API virtual bool on_timeout() override; | |||||
protected: | protected: | ||||
//_value引用awaitor保存的值,这样可以尽可能减少创建state的可能。而不必进入没有state就没有value实体被用于返回。 | //_value引用awaitor保存的值,这样可以尽可能减少创建state的可能。而不必进入没有state就没有value实体被用于返回。 | ||||
//在调用on_notify()或on_timeout()任意之一后,置为nullptr。 | //在调用on_notify()或on_timeout()任意之一后,置为nullptr。 | ||||
, _value(&val) | , _value(&val) | ||||
{} | {} | ||||
virtual void on_cancel() noexcept override; | |||||
virtual bool on_notify(event_v2_impl* eptr) override; | |||||
virtual bool on_timeout() override; | |||||
LIBRF_API virtual void on_cancel() noexcept override; | |||||
LIBRF_API virtual bool on_notify(event_v2_impl* eptr) override; | |||||
LIBRF_API virtual bool on_timeout() override; | |||||
std::atomic<intptr_t> _counter; | std::atomic<intptr_t> _counter; | ||||
protected: | protected: |
/** | /** | ||||
* @brief 通过错误码获得错误描述字符串。 | * @brief 通过错误码获得错误描述字符串。 | ||||
*/ | */ | ||||
const char* get_error_string(error_code fe, const char* classname); | |||||
LIBRF_API const char* get_error_string(error_code fe, const char* classname); | |||||
/** | /** | ||||
* @brief 在操作future_t<>时产生的异常。 | * @brief 在操作future_t<>时产生的异常。 | ||||
*/ | */ | ||||
const char* get_error_string(error_code fe, const char* classname); | |||||
struct future_exception : std::logic_error | struct future_exception : std::logic_error | ||||
{ | { | ||||
error_code _error; | error_code _error; |
#endif // unlikely | #endif // unlikely | ||||
#endif // defined(__clang__) || defined(__GNUC__) | #endif // defined(__clang__) || defined(__GNUC__) | ||||
#ifdef RESUMEF_USE_SHARD_LIBRARY | |||||
#ifndef LIBRF_USE_STATIC_LIBRARY | |||||
# if _WIN32 | # if _WIN32 | ||||
# ifdef RESUMEF_DYNAMIC_EXPORTS | |||||
# ifdef LIBRF_DYNAMIC_EXPORTS | |||||
# define LIBRF_API __declspec(dllexport) | # define LIBRF_API __declspec(dllexport) | ||||
# else //RESUMEF_DYNAMIC_EXPORTS | # else //RESUMEF_DYNAMIC_EXPORTS | ||||
# define LIBRF_API __declspec(dllimport) | # define LIBRF_API __declspec(dllimport) |
> | > | ||||
static void unlock(void* unique_address, _Mtxs&... mtxs); | static void unlock(void* unique_address, _Mtxs&... mtxs); | ||||
mutex_t(); | |||||
LIBRF_API mutex_t(); | |||||
/** | /** | ||||
* @brief 构造一个无效的mutex_t。 | * @brief 构造一个无效的mutex_t。 | ||||
*/ | */ | ||||
mutex_t(std::adopt_lock_t) noexcept; | |||||
~mutex_t() noexcept; | |||||
LIBRF_API mutex_t(std::adopt_lock_t) noexcept; | |||||
LIBRF_API ~mutex_t() noexcept; | |||||
mutex_t(const mutex_t&) = default; | mutex_t(const mutex_t&) = default; | ||||
mutex_t(mutex_t&&) = default; | mutex_t(mutex_t&&) = default; |
: _value(&val) | : _value(&val) | ||||
{} | {} | ||||
virtual void resume() override; | |||||
virtual bool has_handler() const noexcept override; | |||||
virtual state_base_t* get_parent() const noexcept override; | |||||
LIBRF_API virtual void resume() override; | |||||
LIBRF_API virtual bool has_handler() const noexcept override; | |||||
LIBRF_API virtual state_base_t* get_parent() const noexcept override; | |||||
void on_cancel() noexcept; | |||||
bool on_notify(mutex_v2_impl* eptr); | |||||
bool on_timeout(); | |||||
LIBRF_API void on_cancel() noexcept; | |||||
LIBRF_API bool on_notify(mutex_v2_impl* eptr); | |||||
LIBRF_API bool on_timeout(); | |||||
void add_timeout_timer(std::chrono::system_clock::time_point tp); | |||||
LIBRF_API void add_timeout_timer(std::chrono::system_clock::time_point tp); | |||||
inline void on_await_suspend(coroutine_handle<> handler, scheduler_t* sch, state_base_t* root) noexcept | inline void on_await_suspend(coroutine_handle<> handler, scheduler_t* sch, state_base_t* root) noexcept | ||||
{ | { | ||||
return _owner.load(std::memory_order_relaxed); | return _owner.load(std::memory_order_relaxed); | ||||
} | } | ||||
bool try_lock(void* sch); //内部加锁 | |||||
bool try_lock_until(clock_type::time_point tp, void* sch); //内部加锁 | |||||
bool unlock(void* sch); //内部加锁 | |||||
void lock_until_succeed(void* sch); //内部加锁 | |||||
LIBRF_API bool try_lock(void* sch); //内部加锁 | |||||
LIBRF_API bool try_lock_until(clock_type::time_point tp, void* sch); //内部加锁 | |||||
LIBRF_API bool unlock(void* sch); //内部加锁 | |||||
LIBRF_API void lock_until_succeed(void* sch); //内部加锁 | |||||
public: | public: | ||||
static constexpr bool USE_SPINLOCK = true; | static constexpr bool USE_SPINLOCK = true; | ||||
using state_mutex_ptr = counted_ptr<state_mutex_t>; | using state_mutex_ptr = counted_ptr<state_mutex_t>; | ||||
using wait_queue_type = std::list<state_mutex_ptr>; | using wait_queue_type = std::list<state_mutex_ptr>; | ||||
bool try_lock_lockless(void* sch) noexcept; //内部不加锁,加锁由外部来进行 | |||||
void add_wait_list_lockless(state_mutex_t* state); //内部不加锁,加锁由外部来进行 | |||||
LIBRF_API bool try_lock_lockless(void* sch) noexcept; //内部不加锁,加锁由外部来进行 | |||||
LIBRF_API void add_wait_list_lockless(state_mutex_t* state); //内部不加锁,加锁由外部来进行 | |||||
lock_type _lock; //保证访问本对象是线程安全的 | lock_type _lock; //保证访问本对象是线程安全的 | ||||
private: | private: |
*/ | */ | ||||
struct task_t | struct task_t | ||||
{ | { | ||||
task_t() noexcept; | |||||
virtual ~task_t(); | |||||
LIBRF_API task_t() noexcept; | |||||
LIBRF_API virtual ~task_t(); | |||||
/** | /** | ||||
* @brief 获取stop_source,第一次获取时,会生成一个有效的stop_source。 | * @brief 获取stop_source,第一次获取时,会生成一个有效的stop_source。 | ||||
* @return stop_source | * @return stop_source | ||||
*/ | */ | ||||
const stop_source & get_stop_source(); | |||||
LIBRF_API const stop_source & get_stop_source(); | |||||
/** | /** | ||||
* @brief 获取一个跟stop_source绑定的,新的stop_token。 | * @brief 获取一个跟stop_source绑定的,新的stop_token。 |
namespace librf | namespace librf | ||||
{ | { | ||||
/** | |||||
* @brief 获得当前线程下的调度器。 | |||||
*/ | |||||
LIBRF_API scheduler_t* this_scheduler(); | |||||
/** | /** | ||||
* @brief 协程调度器。 | * @brief 协程调度器。 | ||||
* @details librf的设计原则之一,就是要将协程绑定在固定的调度器里执行。 | * @details librf的设计原则之一,就是要将协程绑定在固定的调度器里执行。 | ||||
timer_mgr_ptr _timer; | timer_mgr_ptr _timer; | ||||
task_t* new_task(task_t* task); | |||||
LIBRF_API task_t* new_task(task_t* task); | |||||
//void cancel_all_task_(); | //void cancel_all_task_(); | ||||
public: | public: | ||||
/** | /** | ||||
* @details 这是协程调度器提供的主要接口。同一个调度器非线程安全,不可重入。\n | * @details 这是协程调度器提供的主要接口。同一个调度器非线程安全,不可重入。\n | ||||
* 调用者要保证此函数始终在同一个线程里调用。 | * 调用者要保证此函数始终在同一个线程里调用。 | ||||
*/ | */ | ||||
bool run_one_batch(); | |||||
LIBRF_API bool run_one_batch(); | |||||
/** | /** | ||||
* @brief 循环运行所有的协程,直到所有协程都运行完成。 | * @brief 循环运行所有的协程,直到所有协程都运行完成。 | ||||
* @details 通常用于测试代码。 | * @details 通常用于测试代码。 | ||||
*/ | */ | ||||
void run_until_notask(); | |||||
LIBRF_API void run_until_notask(); | |||||
//void break_all(); | //void break_all(); | ||||
} | } | ||||
#ifndef DOXYGEN_SKIP_PROPERTY | #ifndef DOXYGEN_SKIP_PROPERTY | ||||
void add_generator(state_base_t* sptr); | |||||
void del_final(state_base_t* sptr); | |||||
std::unique_ptr<task_t> del_switch(state_base_t* sptr); | |||||
void add_switch(std::unique_ptr<task_t> task); | |||||
task_t* find_task(state_base_t* sptr) const noexcept; | |||||
LIBRF_API void add_generator(state_base_t* sptr); | |||||
LIBRF_API void del_final(state_base_t* sptr); | |||||
LIBRF_API std::unique_ptr<task_t> del_switch(state_base_t* sptr); | |||||
LIBRF_API void add_switch(std::unique_ptr<task_t> task); | |||||
LIBRF_API task_t* find_task(state_base_t* sptr) const noexcept; | |||||
friend struct local_scheduler_t; | friend struct local_scheduler_t; | ||||
protected: | protected: | ||||
scheduler_t(); | |||||
LIBRF_API scheduler_t(); | |||||
public: | public: | ||||
~scheduler_t(); | |||||
LIBRF_API ~scheduler_t(); | |||||
scheduler_t(scheduler_t&& right_) = delete; | scheduler_t(scheduler_t&& right_) = delete; | ||||
scheduler_t& operator = (scheduler_t&& right_) = delete; | scheduler_t& operator = (scheduler_t&& right_) = delete; | ||||
scheduler_t(const scheduler_t&) = delete; | scheduler_t(const scheduler_t&) = delete; | ||||
scheduler_t& operator = (const scheduler_t&) = delete; | scheduler_t& operator = (const scheduler_t&) = delete; | ||||
static scheduler_t g_scheduler; | |||||
LIBRF_API static scheduler_t g_scheduler; | |||||
#endif //DOXYGEN_SKIP_PROPERTY | #endif //DOXYGEN_SKIP_PROPERTY | ||||
}; | }; | ||||
/** | /** | ||||
* @brief 尽可能的创建一个线程相关的调度器。 | * @brief 尽可能的创建一个线程相关的调度器。 | ||||
*/ | */ | ||||
local_scheduler_t(); | |||||
LIBRF_API local_scheduler_t(); | |||||
/** | /** | ||||
* @brief 将指定的调度器绑定到当前线程上。 | * @brief 将指定的调度器绑定到当前线程上。 | ||||
*/ | */ | ||||
local_scheduler_t(scheduler_t & sch) noexcept; | |||||
LIBRF_API local_scheduler_t(scheduler_t & sch) noexcept; | |||||
/** | /** | ||||
* @brief 如果当前线程绑定的调度器由local_scheduler_t所创建,则会销毁调度器,并解绑线程。 | * @brief 如果当前线程绑定的调度器由local_scheduler_t所创建,则会销毁调度器,并解绑线程。 | ||||
*/ | */ | ||||
~local_scheduler_t(); | |||||
LIBRF_API ~local_scheduler_t(); | |||||
local_scheduler_t(local_scheduler_t&& right_) = delete; | local_scheduler_t(local_scheduler_t&& right_) = delete; | ||||
local_scheduler_t& operator = (local_scheduler_t&& right_) = delete; | local_scheduler_t& operator = (local_scheduler_t&& right_) = delete; |
* @return [co_await] void | * @return [co_await] void | ||||
* @throw timer_canceled_exception 如果定时器被取消,则抛此异常。 | * @throw timer_canceled_exception 如果定时器被取消,则抛此异常。 | ||||
*/ | */ | ||||
future_t<> sleep_until_(std::chrono::system_clock::time_point tp_, scheduler_t& scheduler_); | |||||
LIBRF_API future_t<> sleep_until_(std::chrono::system_clock::time_point tp_, scheduler_t& scheduler_); | |||||
/** | /** | ||||
* @brief 协程专用的睡眠功能。 | * @brief 协程专用的睡眠功能。 |
// 二、没有co_await操作,直接加入到了调度器里,则_coro在初始时为nullptr。调度器需要特殊处理此种情况。 | // 二、没有co_await操作,直接加入到了调度器里,则_coro在初始时为nullptr。调度器需要特殊处理此种情况。 | ||||
coroutine_handle<> _coro; | coroutine_handle<> _coro; | ||||
virtual ~state_base_t(); | |||||
LIBRF_API virtual ~state_base_t(); | |||||
private: | private: | ||||
virtual void destroy_deallocate(); | |||||
LIBRF_API virtual void destroy_deallocate(); | |||||
public: | public: | ||||
virtual void resume() = 0; | virtual void resume() = 0; | ||||
virtual bool has_handler() const noexcept = 0; | virtual bool has_handler() const noexcept = 0; | ||||
virtual state_base_t* get_parent() const noexcept; | |||||
LIBRF_API virtual state_base_t* get_parent() const noexcept; | |||||
void set_scheduler(scheduler_t* sch) noexcept | void set_scheduler(scheduler_t* sch) noexcept | ||||
{ | { | ||||
struct state_generator_t : public state_base_t | struct state_generator_t : public state_base_t | ||||
{ | { | ||||
private: | private: | ||||
virtual void destroy_deallocate() override; | |||||
LIBRF_API virtual void destroy_deallocate() override; | |||||
state_generator_t() = default; | state_generator_t() = default; | ||||
public: | public: | ||||
virtual void resume() override; | |||||
virtual bool has_handler() const noexcept override; | |||||
LIBRF_API virtual void resume() override; | |||||
LIBRF_API virtual bool has_handler() const noexcept override; | |||||
bool switch_scheduler_await_suspend(scheduler_t* sch); | |||||
LIBRF_API bool switch_scheduler_await_suspend(scheduler_t* sch); | |||||
void set_initial_suspend(coroutine_handle<> handler) noexcept | void set_initial_suspend(coroutine_handle<> handler) noexcept | ||||
{ | { | ||||
return new(_Ptr) state_generator_t(); | return new(_Ptr) state_generator_t(); | ||||
} | } | ||||
#endif | #endif | ||||
static state_generator_t* _Alloc_state(); | |||||
LIBRF_API static state_generator_t* _Alloc_state(); | |||||
}; | }; | ||||
/** | /** | ||||
_is_future = !awaitor; | _is_future = !awaitor; | ||||
} | } | ||||
public: | public: | ||||
virtual void destroy_deallocate() override; | |||||
virtual void resume() override; | |||||
virtual bool has_handler() const noexcept override; | |||||
virtual state_base_t* get_parent() const noexcept override; | |||||
LIBRF_API virtual void destroy_deallocate() override; | |||||
LIBRF_API virtual void resume() override; | |||||
LIBRF_API virtual bool has_handler() const noexcept override; | |||||
LIBRF_API virtual state_base_t* get_parent() const noexcept override; | |||||
inline bool is_ready() const noexcept | inline bool is_ready() const noexcept | ||||
{ | { | ||||
template<class _PromiseT, typename = std::enable_if_t<traits::is_promise_v<_PromiseT>>> | template<class _PromiseT, typename = std::enable_if_t<traits::is_promise_v<_PromiseT>>> | ||||
void future_await_suspend(coroutine_handle<_PromiseT> handler); | void future_await_suspend(coroutine_handle<_PromiseT> handler); | ||||
bool switch_scheduler_await_suspend(scheduler_t* sch); | |||||
LIBRF_API bool switch_scheduler_await_suspend(scheduler_t* sch); | |||||
template<class _PromiseT, typename = std::enable_if_t<traits::is_promise_v<_PromiseT>>> | template<class _PromiseT, typename = std::enable_if_t<traits::is_promise_v<_PromiseT>>> | ||||
void promise_initial_suspend(coroutine_handle<_PromiseT> handler); | void promise_initial_suspend(coroutine_handle<_PromiseT> handler); | ||||
private: | private: | ||||
explicit state_t(bool awaitor) noexcept :state_future_t(awaitor) {} | explicit state_t(bool awaitor) noexcept :state_future_t(awaitor) {} | ||||
public: | public: | ||||
void future_await_resume(); | |||||
LIBRF_API void future_await_resume(); | |||||
template<class _PromiseT, typename = std::enable_if_t<traits::is_promise_v<_PromiseT>>> | template<class _PromiseT, typename = std::enable_if_t<traits::is_promise_v<_PromiseT>>> | ||||
void promise_yield_value(_PromiseT* promise); | void promise_yield_value(_PromiseT* promise); | ||||
void set_exception(std::exception_ptr e); | |||||
void set_value(); | |||||
LIBRF_API void set_exception(std::exception_ptr e); | |||||
LIBRF_API void set_value(); | |||||
template<class _Exp> | template<class _Exp> | ||||
inline void throw_exception(_Exp e) | inline void throw_exception(_Exp e) |
typedef std::multimap<clock_type::time_point, timer_target_ptr> timer_map_type; | typedef std::multimap<clock_type::time_point, timer_target_ptr> timer_map_type; | ||||
#endif | #endif | ||||
public: | public: | ||||
timer_manager(); | |||||
~timer_manager(); | |||||
LIBRF_API timer_manager(); | |||||
LIBRF_API ~timer_manager(); | |||||
template<class _Rep, class _Period, class _Cb> | template<class _Rep, class _Period, class _Cb> | ||||
timer_target_ptr add(const std::chrono::duration<_Rep, _Period> & dt_, _Cb && cb_) | timer_target_ptr add(const std::chrono::duration<_Rep, _Period> & dt_, _Cb && cb_) | ||||
return{ this, add(tp_, std::forward<_Cb>(cb_)) }; | return{ this, add(tp_, std::forward<_Cb>(cb_)) }; | ||||
} | } | ||||
bool stop(const timer_target_ptr & sptr); | |||||
LIBRF_API bool stop(const timer_target_ptr & sptr); | |||||
inline bool empty() const | inline bool empty() const | ||||
{ | { | ||||
return _runing_timers.empty() && _added_timers.empty(); | return _runing_timers.empty() && _added_timers.empty(); | ||||
} | } | ||||
void clear(); | |||||
void update(); | |||||
LIBRF_API void clear(); | |||||
LIBRF_API void update(); | |||||
#ifndef DOXYGEN_SKIP_PROPERTY | #ifndef DOXYGEN_SKIP_PROPERTY | ||||
template<class _Cb> | template<class _Cb> | ||||
timer_vector_type _added_timers; | timer_vector_type _added_timers; | ||||
timer_map_type _runing_timers; | timer_map_type _runing_timers; | ||||
timer_target_ptr add_(const timer_target_ptr & sptr); | |||||
static void call_target_(const timer_target_ptr & sptr, bool canceld); | |||||
LIBRF_API timer_target_ptr add_(const timer_target_ptr & sptr); | |||||
LIBRF_API static void call_target_(const timer_target_ptr & sptr, bool canceld); | |||||
#endif | #endif | ||||
}; | }; | ||||
{ | { | ||||
struct state_when_t : public state_base_t | struct state_when_t : public state_base_t | ||||
{ | { | ||||
state_when_t(intptr_t counter_); | |||||
LIBRF_API state_when_t(intptr_t counter_); | |||||
virtual void resume() override; | |||||
virtual bool has_handler() const noexcept override; | |||||
LIBRF_API virtual void resume() override; | |||||
LIBRF_API virtual bool has_handler() const noexcept override; | |||||
void on_cancel() noexcept; | |||||
bool on_notify_one(); | |||||
bool on_timeout(); | |||||
LIBRF_API void on_cancel() noexcept; | |||||
LIBRF_API bool on_notify_one(); | |||||
LIBRF_API bool on_timeout(); | |||||
//将自己加入到通知链表里 | //将自己加入到通知链表里 | ||||
template<class _PromiseT, typename = std::enable_if_t<traits::is_promise_v<_PromiseT>>> | template<class _PromiseT, typename = std::enable_if_t<traits::is_promise_v<_PromiseT>>> |
{ | { | ||||
namespace detail | namespace detail | ||||
{ | { | ||||
void state_event_base_t::resume() | |||||
LIBRF_API void state_event_base_t::resume() | |||||
{ | { | ||||
coroutine_handle<> handler = _coro; | coroutine_handle<> handler = _coro; | ||||
if (handler) | if (handler) | ||||
} | } | ||||
} | } | ||||
bool state_event_base_t::has_handler() const noexcept | |||||
LIBRF_API bool state_event_base_t::has_handler() const noexcept | |||||
{ | { | ||||
return (bool)_coro; | return (bool)_coro; | ||||
} | } | ||||
void state_event_t::on_cancel() noexcept | |||||
LIBRF_API void state_event_t::on_cancel() noexcept | |||||
{ | { | ||||
event_v2_impl** oldValue = _value.load(std::memory_order_acquire); | event_v2_impl** oldValue = _value.load(std::memory_order_acquire); | ||||
if (oldValue != nullptr && _value.compare_exchange_strong(oldValue, nullptr, std::memory_order_acq_rel)) | if (oldValue != nullptr && _value.compare_exchange_strong(oldValue, nullptr, std::memory_order_acq_rel)) | ||||
} | } | ||||
} | } | ||||
bool state_event_t::on_notify(event_v2_impl* eptr) | |||||
LIBRF_API bool state_event_t::on_notify(event_v2_impl* eptr) | |||||
{ | { | ||||
event_v2_impl** oldValue = _value.load(std::memory_order_acquire); | event_v2_impl** oldValue = _value.load(std::memory_order_acquire); | ||||
if (oldValue != nullptr && _value.compare_exchange_strong(oldValue, nullptr, std::memory_order_acq_rel)) | if (oldValue != nullptr && _value.compare_exchange_strong(oldValue, nullptr, std::memory_order_acq_rel)) | ||||
return false; | return false; | ||||
} | } | ||||
bool state_event_t::on_timeout() | |||||
LIBRF_API bool state_event_t::on_timeout() | |||||
{ | { | ||||
event_v2_impl** oldValue = _value.load(std::memory_order_acquire); | event_v2_impl** oldValue = _value.load(std::memory_order_acquire); | ||||
if (oldValue != nullptr && _value.compare_exchange_strong(oldValue, nullptr, std::memory_order_acq_rel)) | if (oldValue != nullptr && _value.compare_exchange_strong(oldValue, nullptr, std::memory_order_acq_rel)) | ||||
void state_event_all_t::on_cancel() noexcept | |||||
LIBRF_API void state_event_all_t::on_cancel() noexcept | |||||
{ | { | ||||
intptr_t oldValue = _counter.load(std::memory_order_acquire); | intptr_t oldValue = _counter.load(std::memory_order_acquire); | ||||
if (oldValue >= 0 && _counter.compare_exchange_strong(oldValue, -1, std::memory_order_acq_rel)) | if (oldValue >= 0 && _counter.compare_exchange_strong(oldValue, -1, std::memory_order_acq_rel)) | ||||
} | } | ||||
} | } | ||||
bool state_event_all_t::on_notify(event_v2_impl*) | |||||
LIBRF_API bool state_event_all_t::on_notify(event_v2_impl*) | |||||
{ | { | ||||
intptr_t oldValue = _counter.load(std::memory_order_acquire); | intptr_t oldValue = _counter.load(std::memory_order_acquire); | ||||
if (oldValue <= 0) return false; | if (oldValue <= 0) return false; | ||||
return oldValue >= 1; | return oldValue >= 1; | ||||
} | } | ||||
bool state_event_all_t::on_timeout() | |||||
LIBRF_API bool state_event_all_t::on_timeout() | |||||
{ | { | ||||
intptr_t oldValue = _counter.load(std::memory_order_acquire); | intptr_t oldValue = _counter.load(std::memory_order_acquire); | ||||
if (oldValue >= 0 && _counter.compare_exchange_strong(oldValue, -1, std::memory_order_acq_rel)) | if (oldValue >= 0 && _counter.compare_exchange_strong(oldValue, -1, std::memory_order_acq_rel)) | ||||
event_v2_impl::event_v2_impl(bool initially) noexcept | |||||
LIBRF_API event_v2_impl::event_v2_impl(bool initially) noexcept | |||||
: _counter(initially ? 1 : 0) | : _counter(initially ? 1 : 0) | ||||
{ | { | ||||
} | } | ||||
list.clear(); | list.clear(); | ||||
} | } | ||||
event_v2_impl::~event_v2_impl() | |||||
LIBRF_API event_v2_impl::~event_v2_impl() | |||||
{ | { | ||||
clear_list(_wait_awakes); | clear_list(_wait_awakes); | ||||
} | } | ||||
void event_v2_impl::signal_all() noexcept | |||||
LIBRF_API void event_v2_impl::signal_all() noexcept | |||||
{ | { | ||||
scoped_lock<lock_type> lock_(_lock); | scoped_lock<lock_type> lock_(_lock); | ||||
} | } | ||||
} | } | ||||
void event_v2_impl::signal() noexcept | |||||
LIBRF_API void event_v2_impl::signal() noexcept | |||||
{ | { | ||||
scoped_lock<lock_type> lock_(_lock); | scoped_lock<lock_type> lock_(_lock); | ||||
} | } | ||||
} | } | ||||
event_t::event_t(bool initially) | |||||
LIBRF_API event_t::event_t(bool initially) | |||||
:_event(std::make_shared<detail::event_v2_impl>(initially)) | :_event(std::make_shared<detail::event_v2_impl>(initially)) | ||||
{ | { | ||||
} | } | ||||
event_t::event_t(std::adopt_lock_t) | |||||
LIBRF_API event_t::event_t(std::adopt_lock_t) | |||||
{ | { | ||||
} | } | ||||
event_t::~event_t() | |||||
LIBRF_API event_t::~event_t() | |||||
{ | { | ||||
} | } | ||||
} | } |
{ | { | ||||
namespace detail | namespace detail | ||||
{ | { | ||||
void state_mutex_t::resume() | |||||
LIBRF_API void state_mutex_t::resume() | |||||
{ | { | ||||
coroutine_handle<> handler = _coro; | coroutine_handle<> handler = _coro; | ||||
if (handler) | if (handler) | ||||
} | } | ||||
} | } | ||||
bool state_mutex_t::has_handler() const noexcept | |||||
LIBRF_API bool state_mutex_t::has_handler() const noexcept | |||||
{ | { | ||||
return (bool)_coro; | return (bool)_coro; | ||||
} | } | ||||
state_base_t* state_mutex_t::get_parent() const noexcept | |||||
LIBRF_API state_base_t* state_mutex_t::get_parent() const noexcept | |||||
{ | { | ||||
return _root; | return _root; | ||||
} | } | ||||
void state_mutex_t::on_cancel() noexcept | |||||
LIBRF_API void state_mutex_t::on_cancel() noexcept | |||||
{ | { | ||||
mutex_v2_impl** oldValue = _value.load(std::memory_order_acquire); | mutex_v2_impl** oldValue = _value.load(std::memory_order_acquire); | ||||
if (oldValue != nullptr && _value.compare_exchange_strong(oldValue, nullptr, std::memory_order_acq_rel)) | if (oldValue != nullptr && _value.compare_exchange_strong(oldValue, nullptr, std::memory_order_acq_rel)) | ||||
} | } | ||||
} | } | ||||
bool state_mutex_t::on_notify(mutex_v2_impl* eptr) | |||||
LIBRF_API bool state_mutex_t::on_notify(mutex_v2_impl* eptr) | |||||
{ | { | ||||
assert(eptr != nullptr); | assert(eptr != nullptr); | ||||
return false; | return false; | ||||
} | } | ||||
bool state_mutex_t::on_timeout() | |||||
LIBRF_API bool state_mutex_t::on_timeout() | |||||
{ | { | ||||
mutex_v2_impl** oldValue = _value.load(std::memory_order_acquire); | mutex_v2_impl** oldValue = _value.load(std::memory_order_acquire); | ||||
if (oldValue != nullptr && _value.compare_exchange_strong(oldValue, nullptr, std::memory_order_acq_rel)) | if (oldValue != nullptr && _value.compare_exchange_strong(oldValue, nullptr, std::memory_order_acq_rel)) | ||||
return false; | return false; | ||||
} | } | ||||
void state_mutex_t::add_timeout_timer(std::chrono::system_clock::time_point tp) | |||||
LIBRF_API void state_mutex_t::add_timeout_timer(std::chrono::system_clock::time_point tp) | |||||
{ | { | ||||
this->_thandler = this->_scheduler->timer()->add_handler(tp, | this->_thandler = this->_scheduler->timer()->add_handler(tp, | ||||
[st = counted_ptr<state_mutex_t>{ this }](bool canceld) | [st = counted_ptr<state_mutex_t>{ this }](bool canceld) | ||||
void mutex_v2_impl::lock_until_succeed(void* sch) | |||||
LIBRF_API void mutex_v2_impl::lock_until_succeed(void* sch) | |||||
{ | { | ||||
assert(sch != nullptr); | assert(sch != nullptr); | ||||
} | } | ||||
} | } | ||||
bool mutex_v2_impl::try_lock(void* sch) | |||||
LIBRF_API bool mutex_v2_impl::try_lock(void* sch) | |||||
{ | { | ||||
assert(sch != nullptr); | assert(sch != nullptr); | ||||
return try_lock_lockless(sch); | return try_lock_lockless(sch); | ||||
} | } | ||||
bool mutex_v2_impl::try_lock_until(clock_type::time_point tp, void* sch) | |||||
LIBRF_API bool mutex_v2_impl::try_lock_until(clock_type::time_point tp, void* sch) | |||||
{ | { | ||||
assert(sch != nullptr); | assert(sch != nullptr); | ||||
return false; | return false; | ||||
} | } | ||||
bool mutex_v2_impl::try_lock_lockless(void* sch) noexcept | |||||
LIBRF_API bool mutex_v2_impl::try_lock_lockless(void* sch) noexcept | |||||
{ | { | ||||
assert(sch != nullptr); | assert(sch != nullptr); | ||||
return false; | return false; | ||||
} | } | ||||
bool mutex_v2_impl::unlock(void* sch) | |||||
LIBRF_API bool mutex_v2_impl::unlock(void* sch) | |||||
{ | { | ||||
assert(sch != nullptr); | assert(sch != nullptr); | ||||
return false; | return false; | ||||
} | } | ||||
void mutex_v2_impl::add_wait_list_lockless(state_mutex_t* state) | |||||
LIBRF_API void mutex_v2_impl::add_wait_list_lockless(state_mutex_t* state) | |||||
{ | { | ||||
assert(state != nullptr); | assert(state != nullptr); | ||||
} | } | ||||
} | } | ||||
mutex_t::mutex_t() | |||||
LIBRF_API mutex_t::mutex_t() | |||||
: _mutex(std::make_shared<detail::mutex_v2_impl>()) | : _mutex(std::make_shared<detail::mutex_v2_impl>()) | ||||
{ | { | ||||
} | } | ||||
mutex_t::mutex_t(std::adopt_lock_t) noexcept | |||||
LIBRF_API mutex_t::mutex_t(std::adopt_lock_t) noexcept | |||||
{ | { | ||||
} | } | ||||
mutex_t::~mutex_t() noexcept | |||||
LIBRF_API mutex_t::~mutex_t() noexcept | |||||
{ | { | ||||
} | } | ||||
} | } |
namespace librf | namespace librf | ||||
{ | { | ||||
task_t::task_t() noexcept | |||||
LIBRF_API task_t::task_t() noexcept | |||||
: _stop(nostopstate) | : _stop(nostopstate) | ||||
{ | { | ||||
} | } | ||||
task_t::~task_t() | |||||
LIBRF_API task_t::~task_t() | |||||
{ | { | ||||
} | } | ||||
const stop_source & task_t::get_stop_source() | |||||
LIBRF_API const stop_source & task_t::get_stop_source() | |||||
{ | { | ||||
_stop.make_sure_possible(); | _stop.make_sure_possible(); | ||||
return _stop; | return _stop; |
char sz_future_error_buffer[256]; | char sz_future_error_buffer[256]; | ||||
const char * get_error_string(error_code fe, const char * classname) | |||||
LIBRF_API const char * get_error_string(error_code fe, const char * classname) | |||||
{ | { | ||||
if (classname) | if (classname) | ||||
{ | { | ||||
thread_local scheduler_t * th_scheduler_ptr = nullptr; | thread_local scheduler_t * th_scheduler_ptr = nullptr; | ||||
//获得当前线程下的调度器 | //获得当前线程下的调度器 | ||||
scheduler_t * this_scheduler() | |||||
LIBRF_API scheduler_t * this_scheduler() | |||||
{ | { | ||||
return th_scheduler_ptr ? th_scheduler_ptr : &scheduler_t::g_scheduler; | return th_scheduler_ptr ? th_scheduler_ptr : &scheduler_t::g_scheduler; | ||||
} | } | ||||
local_scheduler_t::local_scheduler_t() | |||||
LIBRF_API local_scheduler_t::local_scheduler_t() | |||||
{ | { | ||||
if (th_scheduler_ptr == nullptr) | if (th_scheduler_ptr == nullptr) | ||||
{ | { | ||||
} | } | ||||
} | } | ||||
local_scheduler_t::local_scheduler_t(scheduler_t& sch) noexcept | |||||
LIBRF_API local_scheduler_t::local_scheduler_t(scheduler_t& sch) noexcept | |||||
{ | { | ||||
if (th_scheduler_ptr == nullptr) | if (th_scheduler_ptr == nullptr) | ||||
{ | { | ||||
_scheduler_ptr = nullptr; | _scheduler_ptr = nullptr; | ||||
} | } | ||||
local_scheduler_t::~local_scheduler_t() | |||||
LIBRF_API local_scheduler_t::~local_scheduler_t() | |||||
{ | { | ||||
if (th_scheduler_ptr == _scheduler_ptr) | if (th_scheduler_ptr == _scheduler_ptr) | ||||
th_scheduler_ptr = nullptr; | th_scheduler_ptr = nullptr; | ||||
delete _scheduler_ptr; | delete _scheduler_ptr; | ||||
} | } | ||||
scheduler_t::scheduler_t() | |||||
LIBRF_API scheduler_t::scheduler_t() | |||||
: _timer(std::make_shared<timer_manager>()) | : _timer(std::make_shared<timer_manager>()) | ||||
{ | { | ||||
_runing_states.reserve(1024); | _runing_states.reserve(1024); | ||||
th_scheduler_ptr = this; | th_scheduler_ptr = this; | ||||
} | } | ||||
scheduler_t::~scheduler_t() | |||||
LIBRF_API scheduler_t::~scheduler_t() | |||||
{ | { | ||||
//cancel_all_task_(); | //cancel_all_task_(); | ||||
if (th_scheduler_ptr == this) | if (th_scheduler_ptr == this) | ||||
th_scheduler_ptr = nullptr; | th_scheduler_ptr = nullptr; | ||||
} | } | ||||
task_t* scheduler_t::new_task(task_t * task) | |||||
LIBRF_API task_t* scheduler_t::new_task(task_t * task) | |||||
{ | { | ||||
state_base_t* sptr = task->_state.get(); | state_base_t* sptr = task->_state.get(); | ||||
sptr->set_scheduler(this); | sptr->set_scheduler(this); | ||||
return task; | return task; | ||||
} | } | ||||
std::unique_ptr<task_t> scheduler_t::del_switch(state_base_t* sptr) | |||||
LIBRF_API std::unique_ptr<task_t> scheduler_t::del_switch(state_base_t* sptr) | |||||
{ | { | ||||
#if !RESUMEF_DISABLE_MULT_THREAD | #if !RESUMEF_DISABLE_MULT_THREAD | ||||
scoped_lock<spinlock> __guard(_lock_ready); | scoped_lock<spinlock> __guard(_lock_ready); | ||||
} | } | ||||
*/ | */ | ||||
bool scheduler_t::run_one_batch() | |||||
LIBRF_API bool scheduler_t::run_one_batch() | |||||
{ | { | ||||
this->_timer->update(); | this->_timer->update(); | ||||
return true; | return true; | ||||
} | } | ||||
void scheduler_t::run_until_notask() | |||||
LIBRF_API void scheduler_t::run_until_notask() | |||||
{ | { | ||||
for(;;) | for(;;) | ||||
{ | { | ||||
}; | }; | ||||
} | } | ||||
scheduler_t scheduler_t::g_scheduler; | |||||
LIBRF_API scheduler_t scheduler_t::g_scheduler; | |||||
} | } |
namespace librf | namespace librf | ||||
{ | { | ||||
future_t<> sleep_until_(std::chrono::system_clock::time_point tp_, scheduler_t& scheduler_) | |||||
LIBRF_API future_t<> sleep_until_(std::chrono::system_clock::time_point tp_, scheduler_t& scheduler_) | |||||
{ | { | ||||
awaitable_t<> awaitable; | awaitable_t<> awaitable; | ||||
namespace librf | namespace librf | ||||
{ | { | ||||
state_base_t::~state_base_t() | |||||
LIBRF_API state_base_t::~state_base_t() | |||||
{ | { | ||||
} | } | ||||
void state_base_t::destroy_deallocate() | |||||
LIBRF_API void state_base_t::destroy_deallocate() | |||||
{ | { | ||||
delete this; | delete this; | ||||
} | } | ||||
state_base_t* state_base_t::get_parent() const noexcept | |||||
LIBRF_API state_base_t* state_base_t::get_parent() const noexcept | |||||
{ | { | ||||
return nullptr; | return nullptr; | ||||
} | } | ||||
void state_future_t::destroy_deallocate() | |||||
LIBRF_API void state_future_t::destroy_deallocate() | |||||
{ | { | ||||
size_t _Size = this->_alloc_size; | size_t _Size = this->_alloc_size; | ||||
#if RESUMEF_DEBUG_COUNTER | #if RESUMEF_DEBUG_COUNTER | ||||
return _Al.deallocate(reinterpret_cast<char*>(this), _Size); | return _Al.deallocate(reinterpret_cast<char*>(this), _Size); | ||||
} | } | ||||
state_generator_t* state_generator_t::_Alloc_state() | |||||
LIBRF_API state_generator_t* state_generator_t::_Alloc_state() | |||||
{ | { | ||||
_Alloc_char _Al; | _Alloc_char _Al; | ||||
size_t _Size = _Align_size<state_generator_t>(); | size_t _Size = _Align_size<state_generator_t>(); | ||||
return new(_Ptr) state_generator_t(); | return new(_Ptr) state_generator_t(); | ||||
} | } | ||||
void state_generator_t::destroy_deallocate() | |||||
LIBRF_API void state_generator_t::destroy_deallocate() | |||||
{ | { | ||||
size_t _Size = _Align_size<state_generator_t>(); | size_t _Size = _Align_size<state_generator_t>(); | ||||
#if RESUMEF_INLINE_STATE | #if RESUMEF_INLINE_STATE | ||||
return _Al.deallocate(reinterpret_cast<char*>(this), _Size); | return _Al.deallocate(reinterpret_cast<char*>(this), _Size); | ||||
} | } | ||||
void state_generator_t::resume() | |||||
LIBRF_API void state_generator_t::resume() | |||||
{ | { | ||||
if (likely(_coro)) | if (likely(_coro)) | ||||
{ | { | ||||
} | } | ||||
} | } | ||||
bool state_generator_t::has_handler() const noexcept | |||||
LIBRF_API bool state_generator_t::has_handler() const noexcept | |||||
{ | { | ||||
return (bool)_coro; | return (bool)_coro; | ||||
} | } | ||||
bool state_generator_t::switch_scheduler_await_suspend(scheduler_t* sch) | |||||
LIBRF_API bool state_generator_t::switch_scheduler_await_suspend(scheduler_t* sch) | |||||
{ | { | ||||
assert(sch != nullptr); | assert(sch != nullptr); | ||||
return true; | return true; | ||||
} | } | ||||
state_base_t* state_future_t::get_parent() const noexcept | |||||
LIBRF_API state_base_t* state_future_t::get_parent() const noexcept | |||||
{ | { | ||||
return _parent; | return _parent; | ||||
} | } | ||||
void state_future_t::resume() | |||||
LIBRF_API void state_future_t::resume() | |||||
{ | { | ||||
std::unique_lock<lock_type> __guard(_mtx); | std::unique_lock<lock_type> __guard(_mtx); | ||||
} | } | ||||
} | } | ||||
bool state_future_t::has_handler() const noexcept | |||||
LIBRF_API bool state_future_t::has_handler() const noexcept | |||||
{ | { | ||||
scoped_lock<lock_type> __guard(this->_mtx); | scoped_lock<lock_type> __guard(this->_mtx); | ||||
return has_handler_skip_lock(); | return has_handler_skip_lock(); | ||||
} | } | ||||
bool state_future_t::switch_scheduler_await_suspend(scheduler_t* sch) | |||||
LIBRF_API bool state_future_t::switch_scheduler_await_suspend(scheduler_t* sch) | |||||
{ | { | ||||
assert(sch != nullptr); | assert(sch != nullptr); | ||||
scoped_lock<lock_type> __guard(this->_mtx); | scoped_lock<lock_type> __guard(this->_mtx); | ||||
return true; | return true; | ||||
} | } | ||||
void state_t<void>::future_await_resume() | |||||
LIBRF_API void state_t<void>::future_await_resume() | |||||
{ | { | ||||
scoped_lock<lock_type> __guard(this->_mtx); | scoped_lock<lock_type> __guard(this->_mtx); | ||||
std::rethrow_exception(std::make_exception_ptr(future_exception{error_code::not_ready})); | std::rethrow_exception(std::make_exception_ptr(future_exception{error_code::not_ready})); | ||||
} | } | ||||
void state_t<void>::set_value() | |||||
LIBRF_API void state_t<void>::set_value() | |||||
{ | { | ||||
scoped_lock<lock_type> __guard(this->_mtx); | scoped_lock<lock_type> __guard(this->_mtx); | ||||
this->_has_value.store(result_type::Value, std::memory_order_release); | this->_has_value.store(result_type::Value, std::memory_order_release); | ||||
} | } | ||||
} | } | ||||
void state_t<void>::set_exception(std::exception_ptr e) | |||||
LIBRF_API void state_t<void>::set_exception(std::exception_ptr e) | |||||
{ | { | ||||
scoped_lock<lock_type> __guard(this->_mtx); | scoped_lock<lock_type> __guard(this->_mtx); | ||||
this->_exception = std::move(e); | this->_exception = std::move(e); |
namespace librf | namespace librf | ||||
{ | { | ||||
timer_manager::timer_manager() | |||||
LIBRF_API timer_manager::timer_manager() | |||||
{ | { | ||||
_added_timers.reserve(128); | _added_timers.reserve(128); | ||||
} | } | ||||
timer_manager::~timer_manager() | |||||
LIBRF_API timer_manager::~timer_manager() | |||||
{ | { | ||||
clear(); | clear(); | ||||
} | } | ||||
void timer_manager::call_target_(const timer_target_ptr & sptr, bool canceld) | |||||
LIBRF_API void timer_manager::call_target_(const timer_target_ptr & sptr, bool canceld) | |||||
{ | { | ||||
auto cb = std::move(sptr->cb); | auto cb = std::move(sptr->cb); | ||||
sptr->st = timer_target::State::Invalid; | sptr->st = timer_target::State::Invalid; | ||||
if(cb) cb(canceld); | if(cb) cb(canceld); | ||||
} | } | ||||
void timer_manager::clear() | |||||
LIBRF_API void timer_manager::clear() | |||||
{ | { | ||||
#if !RESUMEF_DISABLE_MULT_THREAD | #if !RESUMEF_DISABLE_MULT_THREAD | ||||
std::unique_lock<spinlock> __lock(_added_mtx); | std::unique_lock<spinlock> __lock(_added_mtx); | ||||
call_target_(kv.second, true); | call_target_(kv.second, true); | ||||
} | } | ||||
detail::timer_target_ptr timer_manager::add_(const timer_target_ptr & sptr) | |||||
LIBRF_API detail::timer_target_ptr timer_manager::add_(const timer_target_ptr & sptr) | |||||
{ | { | ||||
assert(sptr); | assert(sptr); | ||||
assert(sptr->st == timer_target::State::Invalid); | assert(sptr->st == timer_target::State::Invalid); | ||||
return sptr; | return sptr; | ||||
} | } | ||||
bool timer_manager::stop(const timer_target_ptr & sptr) | |||||
LIBRF_API bool timer_manager::stop(const timer_target_ptr & sptr) | |||||
{ | { | ||||
if (!sptr || sptr->st == timer_target::State::Invalid) | if (!sptr || sptr->st == timer_target::State::Invalid) | ||||
return false; | return false; | ||||
return true; | return true; | ||||
} | } | ||||
void timer_manager::update() | |||||
LIBRF_API void timer_manager::update() | |||||
{ | { | ||||
{ | { | ||||
#if !RESUMEF_DISABLE_MULT_THREAD | #if !RESUMEF_DISABLE_MULT_THREAD |
{ | { | ||||
namespace detail | namespace detail | ||||
{ | { | ||||
state_when_t::state_when_t(intptr_t counter_) | |||||
LIBRF_API state_when_t::state_when_t(intptr_t counter_) | |||||
:_counter(counter_) | :_counter(counter_) | ||||
{ | { | ||||
} | } | ||||
void state_when_t::resume() | |||||
LIBRF_API void state_when_t::resume() | |||||
{ | { | ||||
coroutine_handle<> handler = _coro; | coroutine_handle<> handler = _coro; | ||||
if (handler) | if (handler) | ||||
} | } | ||||
} | } | ||||
bool state_when_t::has_handler() const noexcept | |||||
LIBRF_API bool state_when_t::has_handler() const noexcept | |||||
{ | { | ||||
return (bool)_coro; | return (bool)_coro; | ||||
} | } | ||||
void state_when_t::on_cancel() noexcept | |||||
LIBRF_API void state_when_t::on_cancel() noexcept | |||||
{ | { | ||||
scoped_lock<lock_type> lock_(_lock); | scoped_lock<lock_type> lock_(_lock); | ||||
this->_coro = nullptr; | this->_coro = nullptr; | ||||
} | } | ||||
bool state_when_t::on_notify_one() | |||||
LIBRF_API bool state_when_t::on_notify_one() | |||||
{ | { | ||||
scoped_lock<lock_type> lock_(_lock); | scoped_lock<lock_type> lock_(_lock); | ||||
return false; | return false; | ||||
} | } | ||||
bool state_when_t::on_timeout() | |||||
LIBRF_API bool state_when_t::on_timeout() | |||||
{ | { | ||||
scoped_lock<lock_type> lock_(_lock); | scoped_lock<lock_type> lock_(_lock); | ||||