summaryrefslogtreecommitdiff
path: root/src/common
diff options
context:
space:
mode:
Diffstat (limited to 'src/common')
-rw-r--r--src/common/fiber.cpp117
-rw-r--r--src/common/fiber.h9
2 files changed, 11 insertions, 115 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 @@
5#include "common/assert.h" 5#include "common/assert.h"
6#include "common/fiber.h" 6#include "common/fiber.h"
7#include "common/spin_lock.h" 7#include "common/spin_lock.h"
8#include "common/virtual_buffer.h"
8 9
9#if defined(_WIN32) || defined(WIN32)
10#include <windows.h>
11#else
12#include <boost/context/detail/fcontext.hpp> 10#include <boost/context/detail/fcontext.hpp>
13#endif
14 11
15namespace Common { 12namespace Common {
16 13
17constexpr std::size_t default_stack_size = 256 * 1024; // 256kb 14constexpr std::size_t default_stack_size = 256 * 1024;
18 15
19struct Fiber::FiberImpl { 16struct Fiber::FiberImpl {
17 FiberImpl() : stack{default_stack_size}, rewind_stack{default_stack_size} {}
18
19 VirtualBuffer<u8> stack;
20 VirtualBuffer<u8> rewind_stack;
21
20 SpinLock guard{}; 22 SpinLock guard{};
21 std::function<void(void*)> entry_point; 23 std::function<void(void*)> entry_point;
22 std::function<void(void*)> rewind_point; 24 std::function<void(void*)> rewind_point;
@@ -26,17 +28,10 @@ struct Fiber::FiberImpl {
26 bool is_thread_fiber{}; 28 bool is_thread_fiber{};
27 bool released{}; 29 bool released{};
28 30
29#if defined(_WIN32) || defined(WIN32) 31 u8* stack_limit{};
30 LPVOID handle = nullptr; 32 u8* rewind_stack_limit{};
31 LPVOID rewind_handle = nullptr; 33 boost::context::detail::fcontext_t context{};
32#else 34 boost::context::detail::fcontext_t rewind_context{};
33 alignas(64) std::array<u8, default_stack_size> stack;
34 alignas(64) std::array<u8, default_stack_size> rewind_stack;
35 u8* stack_limit;
36 u8* rewind_stack_limit;
37 boost::context::detail::fcontext_t context;
38 boost::context::detail::fcontext_t rewind_context;
39#endif
40}; 35};
41 36
42void Fiber::SetStartParameter(void* new_parameter) { 37void Fiber::SetStartParameter(void* new_parameter) {
@@ -48,95 +43,6 @@ void Fiber::SetRewindPoint(std::function<void(void*)>&& rewind_func, void* rewin
48 impl->rewind_parameter = rewind_param; 43 impl->rewind_parameter = rewind_param;
49} 44}
50 45
51#if defined(_WIN32) || defined(WIN32)
52
53void Fiber::Start() {
54 ASSERT(impl->previous_fiber != nullptr);
55 impl->previous_fiber->impl->guard.unlock();
56 impl->previous_fiber.reset();
57 impl->entry_point(impl->start_parameter);
58 UNREACHABLE();
59}
60
61void Fiber::OnRewind() {
62 ASSERT(impl->handle != nullptr);
63 DeleteFiber(impl->handle);
64 impl->handle = impl->rewind_handle;
65 impl->rewind_handle = nullptr;
66 impl->rewind_point(impl->rewind_parameter);
67 UNREACHABLE();
68}
69
70void Fiber::FiberStartFunc(void* fiber_parameter) {
71 auto* fiber = static_cast<Fiber*>(fiber_parameter);
72 fiber->Start();
73}
74
75void Fiber::RewindStartFunc(void* fiber_parameter) {
76 auto* fiber = static_cast<Fiber*>(fiber_parameter);
77 fiber->OnRewind();
78}
79
80Fiber::Fiber(std::function<void(void*)>&& entry_point_func, void* start_parameter)
81 : impl{std::make_unique<FiberImpl>()} {
82 impl->entry_point = std::move(entry_point_func);
83 impl->start_parameter = start_parameter;
84 impl->handle = CreateFiber(default_stack_size, &FiberStartFunc, this);
85}
86
87Fiber::Fiber() : impl{std::make_unique<FiberImpl>()} {}
88
89Fiber::~Fiber() {
90 if (impl->released) {
91 return;
92 }
93 // Make sure the Fiber is not being used
94 const bool locked = impl->guard.try_lock();
95 ASSERT_MSG(locked, "Destroying a fiber that's still running");
96 if (locked) {
97 impl->guard.unlock();
98 }
99 DeleteFiber(impl->handle);
100}
101
102void Fiber::Exit() {
103 ASSERT_MSG(impl->is_thread_fiber, "Exitting non main thread fiber");
104 if (!impl->is_thread_fiber) {
105 return;
106 }
107 ConvertFiberToThread();
108 impl->guard.unlock();
109 impl->released = true;
110}
111
112void Fiber::Rewind() {
113 ASSERT(impl->rewind_point);
114 ASSERT(impl->rewind_handle == nullptr);
115 impl->rewind_handle = CreateFiber(default_stack_size, &RewindStartFunc, this);
116 SwitchToFiber(impl->rewind_handle);
117}
118
119void Fiber::YieldTo(std::shared_ptr<Fiber> from, std::shared_ptr<Fiber> to) {
120 ASSERT_MSG(from != nullptr, "Yielding fiber is null!");
121 ASSERT_MSG(to != nullptr, "Next fiber is null!");
122 to->impl->guard.lock();
123 to->impl->previous_fiber = from;
124 SwitchToFiber(to->impl->handle);
125 ASSERT(from->impl->previous_fiber != nullptr);
126 from->impl->previous_fiber->impl->guard.unlock();
127 from->impl->previous_fiber.reset();
128}
129
130std::shared_ptr<Fiber> Fiber::ThreadToFiber() {
131 std::shared_ptr<Fiber> fiber = std::shared_ptr<Fiber>{new Fiber()};
132 fiber->impl->guard.lock();
133 fiber->impl->handle = ConvertThreadToFiber(nullptr);
134 fiber->impl->is_thread_fiber = true;
135 return fiber;
136}
137
138#else
139
140void Fiber::Start(boost::context::detail::transfer_t& transfer) { 46void Fiber::Start(boost::context::detail::transfer_t& transfer) {
141 ASSERT(impl->previous_fiber != nullptr); 47 ASSERT(impl->previous_fiber != nullptr);
142 impl->previous_fiber->impl->context = transfer.fctx; 48 impl->previous_fiber->impl->context = transfer.fctx;
@@ -229,5 +135,4 @@ std::shared_ptr<Fiber> Fiber::ThreadToFiber() {
229 return fiber; 135 return fiber;
230} 136}
231 137
232#endif
233} // namespace Common 138} // namespace Common
diff --git a/src/common/fiber.h b/src/common/fiber.h
index 5323e8579..f7f587f8c 100644
--- a/src/common/fiber.h
+++ b/src/common/fiber.h
@@ -7,11 +7,9 @@
7#include <functional> 7#include <functional>
8#include <memory> 8#include <memory>
9 9
10#if !defined(_WIN32) && !defined(WIN32)
11namespace boost::context::detail { 10namespace boost::context::detail {
12struct transfer_t; 11struct transfer_t;
13} 12}
14#endif
15 13
16namespace Common { 14namespace Common {
17 15
@@ -59,17 +57,10 @@ public:
59private: 57private:
60 Fiber(); 58 Fiber();
61 59
62#if defined(_WIN32) || defined(WIN32)
63 void OnRewind();
64 void Start();
65 static void FiberStartFunc(void* fiber_parameter);
66 static void RewindStartFunc(void* fiber_parameter);
67#else
68 void OnRewind(boost::context::detail::transfer_t& transfer); 60 void OnRewind(boost::context::detail::transfer_t& transfer);
69 void Start(boost::context::detail::transfer_t& transfer); 61 void Start(boost::context::detail::transfer_t& transfer);
70 static void FiberStartFunc(boost::context::detail::transfer_t transfer); 62 static void FiberStartFunc(boost::context::detail::transfer_t transfer);
71 static void RewindStartFunc(boost::context::detail::transfer_t transfer); 63 static void RewindStartFunc(boost::context::detail::transfer_t transfer);
72#endif
73 64
74 struct FiberImpl; 65 struct FiberImpl;
75 std::unique_ptr<FiberImpl> impl; 66 std::unique_ptr<FiberImpl> impl;