diff options
Diffstat (limited to 'src/common/fiber.cpp')
-rw-r--r-- | src/common/fiber.cpp | 117 |
1 files changed, 11 insertions, 106 deletions
diff --git a/src/common/fiber.cpp b/src/common/fiber.cpp index 3e3029cd1..3c1eefcb7 100644 --- a/src/common/fiber.cpp +++ b/src/common/fiber.cpp @@ -5,18 +5,20 @@ #include "common/assert.h" #include "common/fiber.h" #include "common/spin_lock.h" +#include "common/virtual_buffer.h" -#if defined(_WIN32) || defined(WIN32) -#include <windows.h> -#else #include <boost/context/detail/fcontext.hpp> -#endif namespace Common { -constexpr std::size_t default_stack_size = 256 * 1024; // 256kb +constexpr std::size_t default_stack_size = 256 * 1024; struct Fiber::FiberImpl { + FiberImpl() : stack{default_stack_size}, rewind_stack{default_stack_size} {} + + VirtualBuffer<u8> stack; + VirtualBuffer<u8> rewind_stack; + SpinLock guard{}; std::function<void(void*)> entry_point; std::function<void(void*)> rewind_point; @@ -26,17 +28,10 @@ struct Fiber::FiberImpl { bool is_thread_fiber{}; bool released{}; -#if defined(_WIN32) || defined(WIN32) - LPVOID handle = nullptr; - LPVOID rewind_handle = nullptr; -#else - alignas(64) std::array<u8, default_stack_size> stack; - alignas(64) std::array<u8, default_stack_size> rewind_stack; - u8* stack_limit; - u8* rewind_stack_limit; - boost::context::detail::fcontext_t context; - boost::context::detail::fcontext_t rewind_context; -#endif + u8* stack_limit{}; + u8* rewind_stack_limit{}; + boost::context::detail::fcontext_t context{}; + boost::context::detail::fcontext_t rewind_context{}; }; void Fiber::SetStartParameter(void* new_parameter) { @@ -48,95 +43,6 @@ void Fiber::SetRewindPoint(std::function<void(void*)>&& rewind_func, void* rewin impl->rewind_parameter = rewind_param; } -#if defined(_WIN32) || defined(WIN32) - -void Fiber::Start() { - ASSERT(impl->previous_fiber != nullptr); - impl->previous_fiber->impl->guard.unlock(); - impl->previous_fiber.reset(); - impl->entry_point(impl->start_parameter); - UNREACHABLE(); -} - -void Fiber::OnRewind() { - ASSERT(impl->handle != nullptr); - DeleteFiber(impl->handle); - impl->handle = impl->rewind_handle; - impl->rewind_handle = nullptr; - impl->rewind_point(impl->rewind_parameter); - UNREACHABLE(); -} - -void Fiber::FiberStartFunc(void* fiber_parameter) { - auto* fiber = static_cast<Fiber*>(fiber_parameter); - fiber->Start(); -} - -void Fiber::RewindStartFunc(void* fiber_parameter) { - auto* fiber = static_cast<Fiber*>(fiber_parameter); - fiber->OnRewind(); -} - -Fiber::Fiber(std::function<void(void*)>&& entry_point_func, void* start_parameter) - : impl{std::make_unique<FiberImpl>()} { - 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<FiberImpl>()} {} - -Fiber::~Fiber() { - if (impl->released) { - return; - } - // Make sure the Fiber is not being used - const bool locked = impl->guard.try_lock(); - ASSERT_MSG(locked, "Destroying a fiber that's still running"); - if (locked) { - impl->guard.unlock(); - } - DeleteFiber(impl->handle); -} - -void Fiber::Exit() { - ASSERT_MSG(impl->is_thread_fiber, "Exitting non main thread fiber"); - if (!impl->is_thread_fiber) { - return; - } - ConvertFiberToThread(); - impl->guard.unlock(); - impl->released = true; -} - -void Fiber::Rewind() { - ASSERT(impl->rewind_point); - ASSERT(impl->rewind_handle == nullptr); - impl->rewind_handle = CreateFiber(default_stack_size, &RewindStartFunc, this); - SwitchToFiber(impl->rewind_handle); -} - -void Fiber::YieldTo(std::shared_ptr<Fiber> from, std::shared_ptr<Fiber> to) { - ASSERT_MSG(from != nullptr, "Yielding fiber is null!"); - ASSERT_MSG(to != nullptr, "Next fiber is null!"); - to->impl->guard.lock(); - to->impl->previous_fiber = from; - SwitchToFiber(to->impl->handle); - ASSERT(from->impl->previous_fiber != nullptr); - from->impl->previous_fiber->impl->guard.unlock(); - from->impl->previous_fiber.reset(); -} - -std::shared_ptr<Fiber> Fiber::ThreadToFiber() { - std::shared_ptr<Fiber> fiber = std::shared_ptr<Fiber>{new Fiber()}; - fiber->impl->guard.lock(); - fiber->impl->handle = ConvertThreadToFiber(nullptr); - fiber->impl->is_thread_fiber = true; - return fiber; -} - -#else - void Fiber::Start(boost::context::detail::transfer_t& transfer) { ASSERT(impl->previous_fiber != nullptr); impl->previous_fiber->impl->context = transfer.fctx; @@ -229,5 +135,4 @@ std::shared_ptr<Fiber> Fiber::ThreadToFiber() { return fiber; } -#endif } // namespace Common |