summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/common/fiber.cpp58
-rw-r--r--src/common/fiber.h17
2 files changed, 41 insertions, 34 deletions
diff --git a/src/common/fiber.cpp b/src/common/fiber.cpp
index 6ea314d75..f97ad433b 100644
--- a/src/common/fiber.cpp
+++ b/src/common/fiber.cpp
@@ -21,7 +21,7 @@ struct Fiber::FiberImpl {
21 LPVOID rewind_handle = nullptr; 21 LPVOID rewind_handle = nullptr;
22}; 22};
23 23
24void Fiber::start() { 24void Fiber::Start() {
25 ASSERT(previous_fiber != nullptr); 25 ASSERT(previous_fiber != nullptr);
26 previous_fiber->guard.unlock(); 26 previous_fiber->guard.unlock();
27 previous_fiber.reset(); 27 previous_fiber.reset();
@@ -29,7 +29,7 @@ void Fiber::start() {
29 UNREACHABLE(); 29 UNREACHABLE();
30} 30}
31 31
32void Fiber::onRewind() { 32void Fiber::OnRewind() {
33 ASSERT(impl->handle != nullptr); 33 ASSERT(impl->handle != nullptr);
34 DeleteFiber(impl->handle); 34 DeleteFiber(impl->handle);
35 impl->handle = impl->rewind_handle; 35 impl->handle = impl->rewind_handle;
@@ -38,14 +38,14 @@ void Fiber::onRewind() {
38 UNREACHABLE(); 38 UNREACHABLE();
39} 39}
40 40
41void __stdcall Fiber::FiberStartFunc(void* fiber_parameter) { 41void Fiber::FiberStartFunc(void* fiber_parameter) {
42 auto fiber = static_cast<Fiber*>(fiber_parameter); 42 auto fiber = static_cast<Fiber*>(fiber_parameter);
43 fiber->start(); 43 fiber->Start();
44} 44}
45 45
46void __stdcall Fiber::RewindStartFunc(void* fiber_parameter) { 46void Fiber::RewindStartFunc(void* fiber_parameter) {
47 auto fiber = static_cast<Fiber*>(fiber_parameter); 47 auto fiber = static_cast<Fiber*>(fiber_parameter);
48 fiber->onRewind(); 48 fiber->OnRewind();
49} 49}
50 50
51Fiber::Fiber(std::function<void(void*)>&& entry_point_func, void* start_parameter) 51Fiber::Fiber(std::function<void(void*)>&& entry_point_func, void* start_parameter)
@@ -59,8 +59,11 @@ Fiber::Fiber() {
59} 59}
60 60
61Fiber::~Fiber() { 61Fiber::~Fiber() {
62 if (released) {
63 return;
64 }
62 // Make sure the Fiber is not being used 65 // Make sure the Fiber is not being used
63 bool locked = guard.try_lock(); 66 const bool locked = guard.try_lock();
64 ASSERT_MSG(locked, "Destroying a fiber that's still running"); 67 ASSERT_MSG(locked, "Destroying a fiber that's still running");
65 if (locked) { 68 if (locked) {
66 guard.unlock(); 69 guard.unlock();
@@ -75,6 +78,7 @@ void Fiber::Exit() {
75 } 78 }
76 ConvertFiberToThread(); 79 ConvertFiberToThread();
77 guard.unlock(); 80 guard.unlock();
81 released = true;
78} 82}
79 83
80void Fiber::SetRewindPoint(std::function<void(void*)>&& rewind_func, void* start_parameter) { 84void Fiber::SetRewindPoint(std::function<void(void*)>&& rewind_func, void* start_parameter) {
@@ -89,22 +93,21 @@ void Fiber::Rewind() {
89 SwitchToFiber(impl->rewind_handle); 93 SwitchToFiber(impl->rewind_handle);
90} 94}
91 95
92void Fiber::YieldTo(std::shared_ptr<Fiber> from, std::shared_ptr<Fiber> to) { 96void Fiber::YieldTo(std::shared_ptr<Fiber>& from, std::shared_ptr<Fiber>& to) {
93 ASSERT_MSG(from != nullptr, "Yielding fiber is null!"); 97 ASSERT_MSG(from != nullptr, "Yielding fiber is null!");
94 ASSERT_MSG(to != nullptr, "Next fiber is null!"); 98 ASSERT_MSG(to != nullptr, "Next fiber is null!");
95 to->guard.lock(); 99 to->guard.lock();
96 to->previous_fiber = from; 100 to->previous_fiber = from;
97 SwitchToFiber(to->impl->handle); 101 SwitchToFiber(to->impl->handle);
98 auto previous_fiber = from->previous_fiber; 102 ASSERT(from->previous_fiber != nullptr);
99 ASSERT(previous_fiber != nullptr); 103 from->previous_fiber->guard.unlock();
100 previous_fiber->guard.unlock(); 104 from->previous_fiber.reset();
101 previous_fiber.reset();
102} 105}
103 106
104std::shared_ptr<Fiber> Fiber::ThreadToFiber() { 107std::shared_ptr<Fiber> Fiber::ThreadToFiber() {
105 std::shared_ptr<Fiber> fiber = std::shared_ptr<Fiber>{new Fiber()}; 108 std::shared_ptr<Fiber> fiber = std::shared_ptr<Fiber>{new Fiber()};
106 fiber->guard.lock(); 109 fiber->guard.lock();
107 fiber->impl->handle = ConvertThreadToFiber(NULL); 110 fiber->impl->handle = ConvertThreadToFiber(nullptr);
108 fiber->is_thread_fiber = true; 111 fiber->is_thread_fiber = true;
109 return fiber; 112 return fiber;
110} 113}
@@ -120,7 +123,7 @@ struct Fiber::FiberImpl {
120 boost::context::detail::fcontext_t rewind_context; 123 boost::context::detail::fcontext_t rewind_context;
121}; 124};
122 125
123void Fiber::start(boost::context::detail::transfer_t& transfer) { 126void Fiber::Start(boost::context::detail::transfer_t& transfer) {
124 ASSERT(previous_fiber != nullptr); 127 ASSERT(previous_fiber != nullptr);
125 previous_fiber->impl->context = transfer.fctx; 128 previous_fiber->impl->context = transfer.fctx;
126 previous_fiber->guard.unlock(); 129 previous_fiber->guard.unlock();
@@ -129,7 +132,7 @@ void Fiber::start(boost::context::detail::transfer_t& transfer) {
129 UNREACHABLE(); 132 UNREACHABLE();
130} 133}
131 134
132void Fiber::onRewind(boost::context::detail::transfer_t& [[maybe_unused]] transfer) { 135void Fiber::OnRewind([[maybe_unused]] boost::context::detail::transfer_t& transfer) {
133 ASSERT(impl->context != nullptr); 136 ASSERT(impl->context != nullptr);
134 impl->context = impl->rewind_context; 137 impl->context = impl->rewind_context;
135 impl->rewind_context = nullptr; 138 impl->rewind_context = nullptr;
@@ -142,17 +145,16 @@ void Fiber::onRewind(boost::context::detail::transfer_t& [[maybe_unused]] transf
142 145
143void Fiber::FiberStartFunc(boost::context::detail::transfer_t transfer) { 146void Fiber::FiberStartFunc(boost::context::detail::transfer_t transfer) {
144 auto fiber = static_cast<Fiber*>(transfer.data); 147 auto fiber = static_cast<Fiber*>(transfer.data);
145 fiber->start(transfer); 148 fiber->Start(transfer);
146} 149}
147 150
148void Fiber::RewindStartFunc(boost::context::detail::transfer_t transfer) { 151void Fiber::RewindStartFunc(boost::context::detail::transfer_t transfer) {
149 auto fiber = static_cast<Fiber*>(transfer.data); 152 auto fiber = static_cast<Fiber*>(transfer.data);
150 fiber->onRewind(transfer); 153 fiber->OnRewind(transfer);
151} 154}
152 155
153Fiber::Fiber(std::function<void(void*)>&& entry_point_func, void* start_parameter) 156Fiber::Fiber(std::function<void(void*)>&& entry_point_func, void* start_parameter)
154 : guard{}, entry_point{std::move(entry_point_func)}, start_parameter{start_parameter}, 157 : entry_point{std::move(entry_point_func)}, start_parameter{start_parameter} {
155 previous_fiber{} {
156 impl = std::make_unique<FiberImpl>(); 158 impl = std::make_unique<FiberImpl>();
157 impl->stack_limit = impl->stack.data(); 159 impl->stack_limit = impl->stack.data();
158 impl->rewind_stack_limit = impl->rewind_stack.data(); 160 impl->rewind_stack_limit = impl->rewind_stack.data();
@@ -171,8 +173,11 @@ Fiber::Fiber() {
171} 173}
172 174
173Fiber::~Fiber() { 175Fiber::~Fiber() {
176 if (released) {
177 return;
178 }
174 // Make sure the Fiber is not being used 179 // Make sure the Fiber is not being used
175 bool locked = guard.try_lock(); 180 const bool locked = guard.try_lock();
176 ASSERT_MSG(locked, "Destroying a fiber that's still running"); 181 ASSERT_MSG(locked, "Destroying a fiber that's still running");
177 if (locked) { 182 if (locked) {
178 guard.unlock(); 183 guard.unlock();
@@ -180,11 +185,13 @@ Fiber::~Fiber() {
180} 185}
181 186
182void Fiber::Exit() { 187void Fiber::Exit() {
188
183 ASSERT_MSG(is_thread_fiber, "Exitting non main thread fiber"); 189 ASSERT_MSG(is_thread_fiber, "Exitting non main thread fiber");
184 if (!is_thread_fiber) { 190 if (!is_thread_fiber) {
185 return; 191 return;
186 } 192 }
187 guard.unlock(); 193 guard.unlock();
194 released = true;
188} 195}
189 196
190void Fiber::Rewind() { 197void Fiber::Rewind() {
@@ -196,17 +203,16 @@ void Fiber::Rewind() {
196 boost::context::detail::jump_fcontext(impl->rewind_context, this); 203 boost::context::detail::jump_fcontext(impl->rewind_context, this);
197} 204}
198 205
199void Fiber::YieldTo(std::shared_ptr<Fiber> from, std::shared_ptr<Fiber> to) { 206void Fiber::YieldTo(std::shared_ptr<Fiber>& from, std::shared_ptr<Fiber>& to) {
200 ASSERT_MSG(from != nullptr, "Yielding fiber is null!"); 207 ASSERT_MSG(from != nullptr, "Yielding fiber is null!");
201 ASSERT_MSG(to != nullptr, "Next fiber is null!"); 208 ASSERT_MSG(to != nullptr, "Next fiber is null!");
202 to->guard.lock(); 209 to->guard.lock();
203 to->previous_fiber = from; 210 to->previous_fiber = from;
204 auto transfer = boost::context::detail::jump_fcontext(to->impl->context, to.get()); 211 auto transfer = boost::context::detail::jump_fcontext(to->impl->context, to.get());
205 auto previous_fiber = from->previous_fiber; 212 ASSERT(from->previous_fiber != nullptr);
206 ASSERT(previous_fiber != nullptr); 213 from->previous_fiber->impl->context = transfer.fctx;
207 previous_fiber->impl->context = transfer.fctx; 214 from->previous_fiber->guard.unlock();
208 previous_fiber->guard.unlock(); 215 from->previous_fiber.reset();
209 previous_fiber.reset();
210} 216}
211 217
212std::shared_ptr<Fiber> Fiber::ThreadToFiber() { 218std::shared_ptr<Fiber> Fiber::ThreadToFiber() {
diff --git a/src/common/fiber.h b/src/common/fiber.h
index cab7bc4b5..dafc1100e 100644
--- a/src/common/fiber.h
+++ b/src/common/fiber.h
@@ -46,7 +46,7 @@ public:
46 46
47 /// Yields control from Fiber 'from' to Fiber 'to' 47 /// Yields control from Fiber 'from' to Fiber 'to'
48 /// Fiber 'from' must be the currently running fiber. 48 /// Fiber 'from' must be the currently running fiber.
49 static void YieldTo(std::shared_ptr<Fiber> from, std::shared_ptr<Fiber> to); 49 static void YieldTo(std::shared_ptr<Fiber>& from, std::shared_ptr<Fiber>& to);
50 static std::shared_ptr<Fiber> ThreadToFiber(); 50 static std::shared_ptr<Fiber> ThreadToFiber();
51 51
52 void SetRewindPoint(std::function<void(void*)>&& rewind_func, void* start_parameter); 52 void SetRewindPoint(std::function<void(void*)>&& rewind_func, void* start_parameter);
@@ -65,13 +65,13 @@ private:
65 Fiber(); 65 Fiber();
66 66
67#if defined(_WIN32) || defined(WIN32) 67#if defined(_WIN32) || defined(WIN32)
68 void onRewind(); 68 void OnRewind();
69 void start(); 69 void Start();
70 static void FiberStartFunc(void* fiber_parameter); 70 static void FiberStartFunc(void* fiber_parameter);
71 static void RewindStartFunc(void* fiber_parameter); 71 static void RewindStartFunc(void* fiber_parameter);
72#else 72#else
73 void onRewind(boost::context::detail::transfer_t& transfer); 73 void OnRewind(boost::context::detail::transfer_t& transfer);
74 void start(boost::context::detail::transfer_t& transfer); 74 void Start(boost::context::detail::transfer_t& transfer);
75 static void FiberStartFunc(boost::context::detail::transfer_t transfer); 75 static void FiberStartFunc(boost::context::detail::transfer_t transfer);
76 static void RewindStartFunc(boost::context::detail::transfer_t transfer); 76 static void RewindStartFunc(boost::context::detail::transfer_t transfer);
77#endif 77#endif
@@ -79,13 +79,14 @@ private:
79 struct FiberImpl; 79 struct FiberImpl;
80 80
81 SpinLock guard{}; 81 SpinLock guard{};
82 std::function<void(void*)> entry_point{}; 82 std::function<void(void*)> entry_point;
83 std::function<void(void*)> rewind_point{}; 83 std::function<void(void*)> rewind_point;
84 void* rewind_parameter{}; 84 void* rewind_parameter{};
85 void* start_parameter{}; 85 void* start_parameter{};
86 std::shared_ptr<Fiber> previous_fiber{}; 86 std::shared_ptr<Fiber> previous_fiber;
87 std::unique_ptr<FiberImpl> impl; 87 std::unique_ptr<FiberImpl> impl;
88 bool is_thread_fiber{}; 88 bool is_thread_fiber{};
89 bool released{};
89}; 90};
90 91
91} // namespace Common 92} // namespace Common