diff options
Diffstat (limited to 'src/common/fiber.cpp')
| -rw-r--r-- | src/common/fiber.cpp | 55 |
1 files changed, 33 insertions, 22 deletions
diff --git a/src/common/fiber.cpp b/src/common/fiber.cpp index a2c0401c4..a88a30ced 100644 --- a/src/common/fiber.cpp +++ b/src/common/fiber.cpp | |||
| @@ -2,6 +2,7 @@ | |||
| 2 | // Licensed under GPLv2 or any later version | 2 | // Licensed under GPLv2 or any later version |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include "common/assert.h" | ||
| 5 | #include "common/fiber.h" | 6 | #include "common/fiber.h" |
| 6 | #ifdef _MSC_VER | 7 | #ifdef _MSC_VER |
| 7 | #include <windows.h> | 8 | #include <windows.h> |
| @@ -18,11 +19,11 @@ struct Fiber::FiberImpl { | |||
| 18 | }; | 19 | }; |
| 19 | 20 | ||
| 20 | void Fiber::start() { | 21 | void Fiber::start() { |
| 21 | if (previous_fiber) { | 22 | ASSERT(previous_fiber != nullptr); |
| 22 | previous_fiber->guard.unlock(); | 23 | previous_fiber->guard.unlock(); |
| 23 | previous_fiber = nullptr; | 24 | previous_fiber.reset(); |
| 24 | } | ||
| 25 | entry_point(start_parameter); | 25 | entry_point(start_parameter); |
| 26 | UNREACHABLE(); | ||
| 26 | } | 27 | } |
| 27 | 28 | ||
| 28 | void __stdcall Fiber::FiberStartFunc(void* fiber_parameter) | 29 | void __stdcall Fiber::FiberStartFunc(void* fiber_parameter) |
| @@ -43,12 +44,16 @@ Fiber::Fiber() : guard{}, entry_point{}, start_parameter{}, previous_fiber{} { | |||
| 43 | 44 | ||
| 44 | Fiber::~Fiber() { | 45 | Fiber::~Fiber() { |
| 45 | // Make sure the Fiber is not being used | 46 | // Make sure the Fiber is not being used |
| 46 | guard.lock(); | 47 | bool locked = guard.try_lock(); |
| 47 | guard.unlock(); | 48 | ASSERT_MSG(locked, "Destroying a fiber that's still running"); |
| 49 | if (locked) { | ||
| 50 | guard.unlock(); | ||
| 51 | } | ||
| 48 | DeleteFiber(impl->handle); | 52 | DeleteFiber(impl->handle); |
| 49 | } | 53 | } |
| 50 | 54 | ||
| 51 | void Fiber::Exit() { | 55 | void Fiber::Exit() { |
| 56 | ASSERT_MSG(is_thread_fiber, "Exitting non main thread fiber"); | ||
| 52 | if (!is_thread_fiber) { | 57 | if (!is_thread_fiber) { |
| 53 | return; | 58 | return; |
| 54 | } | 59 | } |
| @@ -57,14 +62,15 @@ void Fiber::Exit() { | |||
| 57 | } | 62 | } |
| 58 | 63 | ||
| 59 | void Fiber::YieldTo(std::shared_ptr<Fiber> from, std::shared_ptr<Fiber> to) { | 64 | void Fiber::YieldTo(std::shared_ptr<Fiber> from, std::shared_ptr<Fiber> to) { |
| 65 | ASSERT_MSG(from != nullptr, "Yielding fiber is null!"); | ||
| 66 | ASSERT_MSG(to != nullptr, "Next fiber is null!"); | ||
| 60 | to->guard.lock(); | 67 | to->guard.lock(); |
| 61 | to->previous_fiber = from; | 68 | to->previous_fiber = from; |
| 62 | SwitchToFiber(to->impl->handle); | 69 | SwitchToFiber(to->impl->handle); |
| 63 | auto previous_fiber = from->previous_fiber; | 70 | auto previous_fiber = from->previous_fiber; |
| 64 | if (previous_fiber) { | 71 | ASSERT(previous_fiber != nullptr); |
| 65 | previous_fiber->guard.unlock(); | 72 | previous_fiber->guard.unlock(); |
| 66 | previous_fiber.reset(); | 73 | previous_fiber.reset(); |
| 67 | } | ||
| 68 | } | 74 | } |
| 69 | 75 | ||
| 70 | std::shared_ptr<Fiber> Fiber::ThreadToFiber() { | 76 | std::shared_ptr<Fiber> Fiber::ThreadToFiber() { |
| @@ -85,12 +91,12 @@ struct alignas(64) Fiber::FiberImpl { | |||
| 85 | }; | 91 | }; |
| 86 | 92 | ||
| 87 | void Fiber::start(boost::context::detail::transfer_t& transfer) { | 93 | void Fiber::start(boost::context::detail::transfer_t& transfer) { |
| 88 | if (previous_fiber) { | 94 | ASSERT(previous_fiber != nullptr); |
| 89 | previous_fiber->impl->context = transfer.fctx; | 95 | previous_fiber->impl->context = transfer.fctx; |
| 90 | previous_fiber->guard.unlock(); | 96 | previous_fiber->guard.unlock(); |
| 91 | previous_fiber = nullptr; | 97 | previous_fiber.reset(); |
| 92 | } | ||
| 93 | entry_point(start_parameter); | 98 | entry_point(start_parameter); |
| 99 | UNREACHABLE(); | ||
| 94 | } | 100 | } |
| 95 | 101 | ||
| 96 | void Fiber::FiberStartFunc(boost::context::detail::transfer_t transfer) | 102 | void Fiber::FiberStartFunc(boost::context::detail::transfer_t transfer) |
| @@ -113,11 +119,15 @@ Fiber::Fiber() : guard{}, entry_point{}, start_parameter{}, previous_fiber{} { | |||
| 113 | 119 | ||
| 114 | Fiber::~Fiber() { | 120 | Fiber::~Fiber() { |
| 115 | // Make sure the Fiber is not being used | 121 | // Make sure the Fiber is not being used |
| 116 | guard.lock(); | 122 | bool locked = guard.try_lock(); |
| 117 | guard.unlock(); | 123 | ASSERT_MSG(locked, "Destroying a fiber that's still running"); |
| 124 | if (locked) { | ||
| 125 | guard.unlock(); | ||
| 126 | } | ||
| 118 | } | 127 | } |
| 119 | 128 | ||
| 120 | void Fiber::Exit() { | 129 | void Fiber::Exit() { |
| 130 | ASSERT_MSG(is_thread_fiber, "Exitting non main thread fiber"); | ||
| 121 | if (!is_thread_fiber) { | 131 | if (!is_thread_fiber) { |
| 122 | return; | 132 | return; |
| 123 | } | 133 | } |
| @@ -125,15 +135,16 @@ void Fiber::Exit() { | |||
| 125 | } | 135 | } |
| 126 | 136 | ||
| 127 | void Fiber::YieldTo(std::shared_ptr<Fiber> from, std::shared_ptr<Fiber> to) { | 137 | void Fiber::YieldTo(std::shared_ptr<Fiber> from, std::shared_ptr<Fiber> to) { |
| 138 | ASSERT_MSG(from != nullptr, "Yielding fiber is null!"); | ||
| 139 | ASSERT_MSG(to != nullptr, "Next fiber is null!"); | ||
| 128 | to->guard.lock(); | 140 | to->guard.lock(); |
| 129 | to->previous_fiber = from; | 141 | to->previous_fiber = from; |
| 130 | auto transfer = boost::context::detail::jump_fcontext(to->impl.context, nullptr); | 142 | auto transfer = boost::context::detail::jump_fcontext(to->impl.context, nullptr); |
| 131 | auto previous_fiber = from->previous_fiber; | 143 | auto previous_fiber = from->previous_fiber; |
| 132 | if (previous_fiber) { | 144 | ASSERT(previous_fiber != nullptr); |
| 133 | previous_fiber->impl->context = transfer.fctx; | 145 | previous_fiber->impl->context = transfer.fctx; |
| 134 | previous_fiber->guard.unlock(); | 146 | previous_fiber->guard.unlock(); |
| 135 | previous_fiber.reset(); | 147 | previous_fiber.reset(); |
| 136 | } | ||
| 137 | } | 148 | } |
| 138 | 149 | ||
| 139 | std::shared_ptr<Fiber> Fiber::ThreadToFiber() { | 150 | std::shared_ptr<Fiber> Fiber::ThreadToFiber() { |