From 00fb79b2f3f49335543c57f1d27b057320f3ff05 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Fri, 6 Nov 2020 20:29:54 -0500 Subject: [PATCH] common/fiber: Move all member variables into impl class Hides all of the implementation details for users of the class. This has the benefit of reducing includes and also making the fiber classes movable again. --- src/common/fiber.cpp | 155 +++++++++++++++++++++++-------------------- src/common/fiber.h | 20 +----- 2 files changed, 86 insertions(+), 89 deletions(-) diff --git a/src/common/fiber.cpp b/src/common/fiber.cpp index b209f52fc..3e3029cd1 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 1a027be96..5323e8579 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