From 424b8b5735155b581ed3847d66796d1f0c57e6f3 Mon Sep 17 00:00:00 2001 From: tqcq <99722391+tqcq@users.noreply.github.com> Date: Sun, 16 Jun 2024 00:46:50 +0800 Subject: [PATCH] feat add this_fiber --- CMakeLists.txt | 14 +++++++------- tile/fiber/detail/fiber.cc | 6 +++--- tile/fiber/detail/fiber.h | 7 +++++++ tile/fiber/detail/scheduler.cc | 28 ++++++++++++++++++++++++++++ tile/fiber/detail/scheduler.h | 2 ++ tile/fiber/this_fiber.cc | 23 +++++++++++++++++++++++ tile/fiber/this_fiber.h | 29 +++++++++++++++++++++++++++++ 7 files changed, 99 insertions(+), 10 deletions(-) create mode 100644 tile/fiber/detail/scheduler.cc create mode 100644 tile/fiber/this_fiber.cc create mode 100644 tile/fiber/this_fiber.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 8041709..6e9c8d5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -43,7 +43,7 @@ elseif(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") # set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -static-libgcc -static-libstdc++") # set(CMAKE_C_FLAGS "${CMAKE_CXX_FLAGS} -static-libgcc -static-libstdc++") - set(STATIC_BINARY_FLAGS "-static-libgcc -static-libstdc++") + set(STATIC_BINARY_FLAGS "-static-libgcc -static-libstdc++") set(WHOLE_ARCHIVE_PREFIX "-Wl,--whole-archive") set(WHOLE_ARCHIVE_SUFFIX "-Wl,--no-whole-archive") endif() @@ -62,7 +62,9 @@ get_git_commit_hash(GIT_COMMIT_HASH) get_git_commit_date(GIT_COMMIT_DATE) get_git_commit_subject(GIT_COMMIT_SUBJECT) -set(THIRD_PARTY_INCLUDE_DIRS "third_party/json" "third_party/inja" "third_party/sigslot" "${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include") +set(THIRD_PARTY_INCLUDE_DIRS + "third_party/json" "third_party/inja" "third_party/sigslot" + "${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include") include_directories(${THIRD_PARTY_INCLUDE_DIRS}) add_subdirectory("third_party/zlib") add_subdirectory("third_party/fmt") @@ -74,7 +76,9 @@ add_subdirectory("third_party/glog") add_subdirectory("third_party/context") set(CURL_DISABLE_TESTS ON) -set(CURL_CA_PATH "none" CACHE STRING "" FORCE) +set(CURL_CA_PATH + "none" + CACHE STRING "" FORCE) set(CURL_ENABLE_SSL OFF CACHE BOOL "" FORCE) @@ -260,8 +264,6 @@ if(TILE_BUILD_TESTS) target_sources(${PROJECT_NAME}_test_all PRIVATE ${test_file}) endmacro() - tile_add_test(fiber_detail_fiber_test "tile/fiber/detail/fiber_test.cc") - tile_add_test(base_internal_meta_test "tile/base/internal/meta_test.cc") # tile_add_test(net_internal_http_engine_test # "tile/net/internal/http_engine_test.cc") @@ -349,8 +351,6 @@ if(TILE_BUILD_BENCHMARKS) target_sources(tile_bm_all PRIVATE ${benchmark_file}) endmacro() - tile_add_bm(fiber_detail_fiber_benchmark - "tile/fiber/detail/fiber_benchmark.cc") tile_add_bm(base_casting_benchmark "tile/base/casting_benchmark.cc") tile_add_bm(base_thread_mutex_benchmark "tile/base/thread/mutex_benchmark.cc") tile_add_bm(base_encoding_benchmark "tile/base/encoding_benchmark.cc") diff --git a/tile/fiber/detail/fiber.cc b/tile/fiber/detail/fiber.cc index 25a5ae3..b7b7589 100644 --- a/tile/fiber/detail/fiber.cc +++ b/tile/fiber/detail/fiber.cc @@ -24,21 +24,22 @@ struct alignas(hardware_destructive_interference_size) Fiber::FiberContext { }; void FiberEntry(fcontext_transfer_t t) { - std::function *fn = static_cast *>(t.data); TILE_CHECK_NE(t.data, nullptr); TILE_CHECK_NE(t.fctx, nullptr); + Fiber *self = nullptr; try { // From Resume() t = jump_fcontext(t.fctx, nullptr); - auto self = reinterpret_cast(t.data); + self = reinterpret_cast(t.data); self->caller_->ctx_ = t.fctx; (*fn)(); } catch (const std::exception &e) { TILE_LOG_ERROR("Exception caught in fiber: {}", e.what()); } + self->state_ = FiberState::Terminated; if (GetMasterFiber() != GetCurrentFiber()) { GetMasterFiber()->Resume(); @@ -66,7 +67,6 @@ void SetUpMasterFiber(Fiber *fiber) noexcept { tls_master_fiber = fiber; } std::unique_ptr Fiber::Create(std::function proc) noexcept { return std::unique_ptr(new Fiber(std::move(proc))); - // return make_unique(std::move(proc)); } Fiber::Fiber(std::function proc) diff --git a/tile/fiber/detail/fiber.h b/tile/fiber/detail/fiber.h index de7b45c..b671a4d 100644 --- a/tile/fiber/detail/fiber.h +++ b/tile/fiber/detail/fiber.h @@ -27,8 +27,12 @@ enum class FiberState { Terminated, }; +class Scheduler; + class alignas(hardware_destructive_interference_size) Fiber { public: + using Id = std::uint64_t; + static std::unique_ptr Create(std::function proc = nullptr) noexcept; @@ -43,6 +47,8 @@ public: void ResumeOn(std::function &&cb) noexcept; void Yield(); + Scheduler *scheduler() const { return scheduler_; } + private: TILE_FRIEND_TEST(Fiber, Base); friend Scheduler; @@ -59,6 +65,7 @@ private: FiberState state_{FiberState::Runnable}; void *ctx_{nullptr}; Fiber *caller_{nullptr}; + Scheduler *scheduler_{nullptr}; }; Fiber *GetCurrentFiber() noexcept; Fiber *GetMasterFiber() noexcept; diff --git a/tile/fiber/detail/scheduler.cc b/tile/fiber/detail/scheduler.cc new file mode 100644 index 0000000..5788e96 --- /dev/null +++ b/tile/fiber/detail/scheduler.cc @@ -0,0 +1,28 @@ +#include "tile/fiber/detail/scheduler.h" + +namespace tile { +namespace fiber { +namespace detail { +static thread_local Scheduler *current_scheduler = nullptr; + +void Scheduler::SwitchTo(Fiber *self, Fiber *to) { + TILE_CHECK_EQ(self, GetCurrentFiber()); + + TILE_CHECK(to->state_ == FiberState::Runnable, + "Fiber `to` is not in Runnable."); + TILE_CHECK_NE(self, to, "Switch to yourself result in U.B."); + + to->Resume(); + + TILE_CHECK_EQ(self, GetCurrentFiber()); +} + +void Scheduler::Yield(Fiber *self) { + auto master = GetMasterFiber(); + + master->state_ = FiberState::Runnable; + SwitchTo(self, master); +} +} // namespace detail +} // namespace fiber +} // namespace tile diff --git a/tile/fiber/detail/scheduler.h b/tile/fiber/detail/scheduler.h index 02c5aff..d889ddb 100644 --- a/tile/fiber/detail/scheduler.h +++ b/tile/fiber/detail/scheduler.h @@ -11,6 +11,8 @@ namespace detail { class Scheduler { public: + static Scheduler *Current() noexcept; + void SwitchTo(Fiber *self, Fiber *to); void Yield(Fiber *self); }; diff --git a/tile/fiber/this_fiber.cc b/tile/fiber/this_fiber.cc new file mode 100644 index 0000000..606263a --- /dev/null +++ b/tile/fiber/this_fiber.cc @@ -0,0 +1,23 @@ +#include "tile/fiber/this_fiber.h" + +namespace tile { +namespace this_fiber { + +void Yield() { + auto self = fiber::detail::GetCurrentFiber(); + TILE_CHECK(self, "Yield() should be called in a fiber."); + self->scheduler()->Yield(self); +} + +void SleepUntil(std::chrono::steady_clock::time_point expires_at) {} + +void SleepFor(std::chrono::nanoseconds expires_in) { + SleepUntil(ReadSteadyClock() + expires_in); +} + +Fiber::Id GetId() { + auto self = fiber::detail::GetCurrentFiber(); + TILE_CHECK(self, "GetId() should be called in a fiber."); +} +} // namespace this_fiber +} // namespace tile diff --git a/tile/fiber/this_fiber.h b/tile/fiber/this_fiber.h new file mode 100644 index 0000000..ba0c46a --- /dev/null +++ b/tile/fiber/this_fiber.h @@ -0,0 +1,29 @@ +#include "tile/fiber/detail/fiber.h" +#include "tile/fiber/detail/scheduler.h" + +#include "tile/base/chrono.h" + +namespace tile { +namespace this_fiber { + +using Fiber = fiber::detail::Fiber; + +void Yield(); + +void SleepUntil(std::chrono::steady_clock::time_point expires_at); +void SleepFor(std::chrono::nanoseconds expires_in); + +template +void SleepFor(std::chrono::time_point expires_at) { + SleepUntil(ReadSteadyClock() + (expires_at - Clock::now())); +} + +template +void SleepFor(std::chrono::duration expires_in) { + return SleepFor(static_cast(expires_in)); +} + +Fiber::Id GetId(); + +} // namespace this_fiber +} // namespace tile