diff options
Diffstat (limited to 'src/common/fiber.cpp')
| -rw-r--r-- | src/common/fiber.cpp | 58 |
1 files changed, 32 insertions, 26 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 | ||
| 24 | void Fiber::start() { | 24 | void 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 | ||
| 32 | void Fiber::onRewind() { | 32 | void 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 | ||
| 41 | void __stdcall Fiber::FiberStartFunc(void* fiber_parameter) { | 41 | void 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 | ||
| 46 | void __stdcall Fiber::RewindStartFunc(void* fiber_parameter) { | 46 | void 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 | ||
| 51 | Fiber::Fiber(std::function<void(void*)>&& entry_point_func, void* start_parameter) | 51 | Fiber::Fiber(std::function<void(void*)>&& entry_point_func, void* start_parameter) |
| @@ -59,8 +59,11 @@ Fiber::Fiber() { | |||
| 59 | } | 59 | } |
| 60 | 60 | ||
| 61 | Fiber::~Fiber() { | 61 | Fiber::~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 | ||
| 80 | void Fiber::SetRewindPoint(std::function<void(void*)>&& rewind_func, void* start_parameter) { | 84 | void 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 | ||
| 92 | void Fiber::YieldTo(std::shared_ptr<Fiber> from, std::shared_ptr<Fiber> to) { | 96 | void 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 | ||
| 104 | std::shared_ptr<Fiber> Fiber::ThreadToFiber() { | 107 | std::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 | ||
| 123 | void Fiber::start(boost::context::detail::transfer_t& transfer) { | 126 | void 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 | ||
| 132 | void Fiber::onRewind(boost::context::detail::transfer_t& [[maybe_unused]] transfer) { | 135 | void 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 | ||
| 143 | void Fiber::FiberStartFunc(boost::context::detail::transfer_t transfer) { | 146 | void 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 | ||
| 148 | void Fiber::RewindStartFunc(boost::context::detail::transfer_t transfer) { | 151 | void 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 | ||
| 153 | Fiber::Fiber(std::function<void(void*)>&& entry_point_func, void* start_parameter) | 156 | Fiber::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 | ||
| 173 | Fiber::~Fiber() { | 175 | Fiber::~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 | ||
| 182 | void Fiber::Exit() { | 187 | void 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 | ||
| 190 | void Fiber::Rewind() { | 197 | void 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 | ||
| 199 | void Fiber::YieldTo(std::shared_ptr<Fiber> from, std::shared_ptr<Fiber> to) { | 206 | void 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 | ||
| 212 | std::shared_ptr<Fiber> Fiber::ThreadToFiber() { | 218 | std::shared_ptr<Fiber> Fiber::ThreadToFiber() { |