diff --git a/src/common/fiber.cpp b/src/common/fiber.cpp index b209f52fc4..3e3029cd10 100644 --- a/src/common/fiber.cpp +++ b/src/common/fiber.cpp @@ -4,6 +4,8 @@ #include "common/assert.h" #include "common/fiber.h" +#include "common/spin_lock.h" + #if defined(_WIN32) || defined(WIN32) #include #else @@ -14,18 +16,45 @@ namespace Common { constexpr std::size_t default_stack_size = 256 * 1024; // 256kb -#if defined(_WIN32) || defined(WIN32) - struct Fiber::FiberImpl { + SpinLock guard{}; + std::function entry_point; + std::function rewind_point; + void* rewind_parameter{}; + void* start_parameter{}; + std::shared_ptr previous_fiber; + bool is_thread_fiber{}; + bool released{}; + +#if defined(_WIN32) || defined(WIN32) LPVOID handle = nullptr; LPVOID rewind_handle = nullptr; +#else + alignas(64) std::array stack; + alignas(64) std::array rewind_stack; + u8* stack_limit; + u8* rewind_stack_limit; + boost::context::detail::fcontext_t context; + boost::context::detail::fcontext_t rewind_context; +#endif }; +void Fiber::SetStartParameter(void* new_parameter) { + impl->start_parameter = new_parameter; +} + +void Fiber::SetRewindPoint(std::function&& rewind_func, void* rewind_param) { + impl->rewind_point = std::move(rewind_func); + impl->rewind_parameter = rewind_param; +} + +#if defined(_WIN32) || defined(WIN32) + void Fiber::Start() { - ASSERT(previous_fiber != nullptr); - previous_fiber->guard.unlock(); - previous_fiber.reset(); - entry_point(start_parameter); + ASSERT(impl->previous_fiber != nullptr); + impl->previous_fiber->impl->guard.unlock(); + impl->previous_fiber.reset(); + impl->entry_point(impl->start_parameter); UNREACHABLE(); } @@ -34,58 +63,54 @@ void Fiber::OnRewind() { DeleteFiber(impl->handle); impl->handle = impl->rewind_handle; impl->rewind_handle = nullptr; - rewind_point(rewind_parameter); + impl->rewind_point(impl->rewind_parameter); UNREACHABLE(); } void Fiber::FiberStartFunc(void* fiber_parameter) { - auto fiber = static_cast(fiber_parameter); + auto* fiber = static_cast(fiber_parameter); fiber->Start(); } void Fiber::RewindStartFunc(void* fiber_parameter) { - auto fiber = static_cast(fiber_parameter); + auto* fiber = static_cast(fiber_parameter); fiber->OnRewind(); } Fiber::Fiber(std::function&& entry_point_func, void* start_parameter) - : entry_point{std::move(entry_point_func)}, start_parameter{start_parameter} { - impl = std::make_unique(); + : impl{std::make_unique()} { + impl->entry_point = std::move(entry_point_func); + impl->start_parameter = start_parameter; impl->handle = CreateFiber(default_stack_size, &FiberStartFunc, this); } Fiber::Fiber() : impl{std::make_unique()} {} Fiber::~Fiber() { - if (released) { + if (impl->released) { return; } // Make sure the Fiber is not being used - const bool locked = guard.try_lock(); + const bool locked = impl->guard.try_lock(); ASSERT_MSG(locked, "Destroying a fiber that's still running"); if (locked) { - guard.unlock(); + impl->guard.unlock(); } DeleteFiber(impl->handle); } void Fiber::Exit() { - ASSERT_MSG(is_thread_fiber, "Exitting non main thread fiber"); - if (!is_thread_fiber) { + ASSERT_MSG(impl->is_thread_fiber, "Exitting non main thread fiber"); + if (!impl->is_thread_fiber) { return; } ConvertFiberToThread(); - guard.unlock(); - released = true; -} - -void Fiber::SetRewindPoint(std::function&& rewind_func, void* rewind_param) { - rewind_point = std::move(rewind_func); - rewind_parameter = rewind_param; + impl->guard.unlock(); + impl->released = true; } void Fiber::Rewind() { - ASSERT(rewind_point); + ASSERT(impl->rewind_point); ASSERT(impl->rewind_handle == nullptr); impl->rewind_handle = CreateFiber(default_stack_size, &RewindStartFunc, this); SwitchToFiber(impl->rewind_handle); @@ -94,39 +119,30 @@ void Fiber::Rewind() { void Fiber::YieldTo(std::shared_ptr from, std::shared_ptr to) { ASSERT_MSG(from != nullptr, "Yielding fiber is null!"); ASSERT_MSG(to != nullptr, "Next fiber is null!"); - to->guard.lock(); - to->previous_fiber = from; + to->impl->guard.lock(); + to->impl->previous_fiber = from; SwitchToFiber(to->impl->handle); - ASSERT(from->previous_fiber != nullptr); - from->previous_fiber->guard.unlock(); - from->previous_fiber.reset(); + ASSERT(from->impl->previous_fiber != nullptr); + from->impl->previous_fiber->impl->guard.unlock(); + from->impl->previous_fiber.reset(); } std::shared_ptr Fiber::ThreadToFiber() { std::shared_ptr fiber = std::shared_ptr{new Fiber()}; - fiber->guard.lock(); + fiber->impl->guard.lock(); fiber->impl->handle = ConvertThreadToFiber(nullptr); - fiber->is_thread_fiber = true; + fiber->impl->is_thread_fiber = true; return fiber; } #else -struct Fiber::FiberImpl { - alignas(64) std::array stack; - alignas(64) std::array rewind_stack; - u8* stack_limit; - u8* rewind_stack_limit; - boost::context::detail::fcontext_t context; - boost::context::detail::fcontext_t rewind_context; -}; - void Fiber::Start(boost::context::detail::transfer_t& transfer) { - ASSERT(previous_fiber != nullptr); - previous_fiber->impl->context = transfer.fctx; - previous_fiber->guard.unlock(); - previous_fiber.reset(); - entry_point(start_parameter); + ASSERT(impl->previous_fiber != nullptr); + impl->previous_fiber->impl->context = transfer.fctx; + impl->previous_fiber->impl->guard.unlock(); + impl->previous_fiber.reset(); + impl->entry_point(impl->start_parameter); UNREACHABLE(); } @@ -137,23 +153,24 @@ void Fiber::OnRewind([[maybe_unused]] boost::context::detail::transfer_t& transf u8* tmp = impl->stack_limit; impl->stack_limit = impl->rewind_stack_limit; impl->rewind_stack_limit = tmp; - rewind_point(rewind_parameter); + impl->rewind_point(impl->rewind_parameter); UNREACHABLE(); } void Fiber::FiberStartFunc(boost::context::detail::transfer_t transfer) { - auto fiber = static_cast(transfer.data); + auto* fiber = static_cast(transfer.data); fiber->Start(transfer); } void Fiber::RewindStartFunc(boost::context::detail::transfer_t transfer) { - auto fiber = static_cast(transfer.data); + auto* fiber = static_cast(transfer.data); fiber->OnRewind(transfer); } Fiber::Fiber(std::function&& entry_point_func, void* start_parameter) - : entry_point{std::move(entry_point_func)}, start_parameter{start_parameter} { - impl = std::make_unique(); + : impl{std::make_unique()} { + impl->entry_point = std::move(entry_point_func); + impl->start_parameter = start_parameter; impl->stack_limit = impl->stack.data(); impl->rewind_stack_limit = impl->rewind_stack.data(); u8* stack_base = impl->stack_limit + default_stack_size; @@ -161,37 +178,31 @@ Fiber::Fiber(std::function&& entry_point_func, void* start_paramete boost::context::detail::make_fcontext(stack_base, impl->stack.size(), FiberStartFunc); } -void Fiber::SetRewindPoint(std::function&& rewind_func, void* rewind_param) { - rewind_point = std::move(rewind_func); - rewind_parameter = rewind_param; -} - Fiber::Fiber() : impl{std::make_unique()} {} Fiber::~Fiber() { - if (released) { + if (impl->released) { return; } // Make sure the Fiber is not being used - const bool locked = guard.try_lock(); + const bool locked = impl->guard.try_lock(); ASSERT_MSG(locked, "Destroying a fiber that's still running"); if (locked) { - guard.unlock(); + impl->guard.unlock(); } } void Fiber::Exit() { - - ASSERT_MSG(is_thread_fiber, "Exitting non main thread fiber"); - if (!is_thread_fiber) { + ASSERT_MSG(impl->is_thread_fiber, "Exitting non main thread fiber"); + if (!impl->is_thread_fiber) { return; } - guard.unlock(); - released = true; + impl->guard.unlock(); + impl->released = true; } void Fiber::Rewind() { - ASSERT(rewind_point); + ASSERT(impl->rewind_point); ASSERT(impl->rewind_context == nullptr); u8* stack_base = impl->rewind_stack_limit + default_stack_size; impl->rewind_context = @@ -202,19 +213,19 @@ void Fiber::Rewind() { void Fiber::YieldTo(std::shared_ptr from, std::shared_ptr to) { ASSERT_MSG(from != nullptr, "Yielding fiber is null!"); ASSERT_MSG(to != nullptr, "Next fiber is null!"); - to->guard.lock(); - to->previous_fiber = from; + to->impl->guard.lock(); + to->impl->previous_fiber = from; auto transfer = boost::context::detail::jump_fcontext(to->impl->context, to.get()); - ASSERT(from->previous_fiber != nullptr); - from->previous_fiber->impl->context = transfer.fctx; - from->previous_fiber->guard.unlock(); - from->previous_fiber.reset(); + ASSERT(from->impl->previous_fiber != nullptr); + from->impl->previous_fiber->impl->context = transfer.fctx; + from->impl->previous_fiber->impl->guard.unlock(); + from->impl->previous_fiber.reset(); } std::shared_ptr Fiber::ThreadToFiber() { std::shared_ptr fiber = std::shared_ptr{new Fiber()}; - fiber->guard.lock(); - fiber->is_thread_fiber = true; + fiber->impl->guard.lock(); + fiber->impl->is_thread_fiber = true; return fiber; } diff --git a/src/common/fiber.h b/src/common/fiber.h index 1a027be96f..5323e85793 100644 --- a/src/common/fiber.h +++ b/src/common/fiber.h @@ -7,9 +7,6 @@ #include #include -#include "common/common_types.h" -#include "common/spin_lock.h" - #if !defined(_WIN32) && !defined(WIN32) namespace boost::context::detail { struct transfer_t; @@ -41,8 +38,8 @@ public: Fiber(const Fiber&) = delete; Fiber& operator=(const Fiber&) = delete; - Fiber(Fiber&&) = delete; - Fiber& operator=(Fiber&&) = delete; + Fiber(Fiber&&) = default; + Fiber& operator=(Fiber&&) = default; /// Yields control from Fiber 'from' to Fiber 'to' /// Fiber 'from' must be the currently running fiber. @@ -57,9 +54,7 @@ public: void Exit(); /// Changes the start parameter of the fiber. Has no effect if the fiber already started - void SetStartParameter(void* new_parameter) { - start_parameter = new_parameter; - } + void SetStartParameter(void* new_parameter); private: Fiber(); @@ -77,16 +72,7 @@ private: #endif struct FiberImpl; - - SpinLock guard{}; - std::function entry_point; - std::function rewind_point; - void* rewind_parameter{}; - void* start_parameter{}; - std::shared_ptr previous_fiber; std::unique_ptr impl; - bool is_thread_fiber{}; - bool released{}; }; } // namespace Common