summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/common/fiber.cpp39
-rw-r--r--src/common/fiber.h2
2 files changed, 39 insertions, 2 deletions
diff --git a/src/common/fiber.cpp b/src/common/fiber.cpp
index f61479e13..6ea314d75 100644
--- a/src/common/fiber.cpp
+++ b/src/common/fiber.cpp
@@ -113,7 +113,11 @@ std::shared_ptr<Fiber> Fiber::ThreadToFiber() {
113 113
114struct Fiber::FiberImpl { 114struct Fiber::FiberImpl {
115 alignas(64) std::array<u8, default_stack_size> stack; 115 alignas(64) std::array<u8, default_stack_size> stack;
116 u8* stack_limit;
117 alignas(64) std::array<u8, default_stack_size> rewind_stack;
118 u8* rewind_stack_limit;
116 boost::context::detail::fcontext_t context; 119 boost::context::detail::fcontext_t context;
120 boost::context::detail::fcontext_t rewind_context;
117}; 121};
118 122
119void Fiber::start(boost::context::detail::transfer_t& transfer) { 123void Fiber::start(boost::context::detail::transfer_t& transfer) {
@@ -125,21 +129,43 @@ void Fiber::start(boost::context::detail::transfer_t& transfer) {
125 UNREACHABLE(); 129 UNREACHABLE();
126} 130}
127 131
132void Fiber::onRewind(boost::context::detail::transfer_t& [[maybe_unused]] transfer) {
133 ASSERT(impl->context != nullptr);
134 impl->context = impl->rewind_context;
135 impl->rewind_context = nullptr;
136 u8* tmp = impl->stack_limit;
137 impl->stack_limit = impl->rewind_stack_limit;
138 impl->rewind_stack_limit = tmp;
139 rewind_point(rewind_parameter);
140 UNREACHABLE();
141}
142
128void Fiber::FiberStartFunc(boost::context::detail::transfer_t transfer) { 143void Fiber::FiberStartFunc(boost::context::detail::transfer_t transfer) {
129 auto fiber = static_cast<Fiber*>(transfer.data); 144 auto fiber = static_cast<Fiber*>(transfer.data);
130 fiber->start(transfer); 145 fiber->start(transfer);
131} 146}
132 147
148void Fiber::RewindStartFunc(boost::context::detail::transfer_t transfer) {
149 auto fiber = static_cast<Fiber*>(transfer.data);
150 fiber->onRewind(transfer);
151}
152
133Fiber::Fiber(std::function<void(void*)>&& entry_point_func, void* start_parameter) 153Fiber::Fiber(std::function<void(void*)>&& entry_point_func, void* start_parameter)
134 : guard{}, entry_point{std::move(entry_point_func)}, start_parameter{start_parameter}, 154 : guard{}, entry_point{std::move(entry_point_func)}, start_parameter{start_parameter},
135 previous_fiber{} { 155 previous_fiber{} {
136 impl = std::make_unique<FiberImpl>(); 156 impl = std::make_unique<FiberImpl>();
137 u8* stack_limit = impl->stack.data(); 157 impl->stack_limit = impl->stack.data();
138 u8* stack_base = stack_limit + default_stack_size; 158 impl->rewind_stack_limit = impl->rewind_stack.data();
159 u8* stack_base = impl->stack_limit + default_stack_size;
139 impl->context = 160 impl->context =
140 boost::context::detail::make_fcontext(stack_base, impl->stack.size(), FiberStartFunc); 161 boost::context::detail::make_fcontext(stack_base, impl->stack.size(), FiberStartFunc);
141} 162}
142 163
164void Fiber::SetRewindPoint(std::function<void(void*)>&& rewind_func, void* start_parameter) {
165 rewind_point = std::move(rewind_func);
166 rewind_parameter = start_parameter;
167}
168
143Fiber::Fiber() { 169Fiber::Fiber() {
144 impl = std::make_unique<FiberImpl>(); 170 impl = std::make_unique<FiberImpl>();
145} 171}
@@ -161,6 +187,15 @@ void Fiber::Exit() {
161 guard.unlock(); 187 guard.unlock();
162} 188}
163 189
190void Fiber::Rewind() {
191 ASSERT(rewind_point);
192 ASSERT(impl->rewind_context == nullptr);
193 u8* stack_base = impl->rewind_stack_limit + default_stack_size;
194 impl->rewind_context =
195 boost::context::detail::make_fcontext(stack_base, impl->stack.size(), RewindStartFunc);
196 boost::context::detail::jump_fcontext(impl->rewind_context, this);
197}
198
164void Fiber::YieldTo(std::shared_ptr<Fiber> from, std::shared_ptr<Fiber> to) { 199void Fiber::YieldTo(std::shared_ptr<Fiber> from, std::shared_ptr<Fiber> to) {
165 ASSERT_MSG(from != nullptr, "Yielding fiber is null!"); 200 ASSERT_MSG(from != nullptr, "Yielding fiber is null!");
166 ASSERT_MSG(to != nullptr, "Next fiber is null!"); 201 ASSERT_MSG(to != nullptr, "Next fiber is null!");
diff --git a/src/common/fiber.h b/src/common/fiber.h
index 3bbd506b5..cab7bc4b5 100644
--- a/src/common/fiber.h
+++ b/src/common/fiber.h
@@ -70,8 +70,10 @@ private:
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 start(boost::context::detail::transfer_t& transfer); 74 void start(boost::context::detail::transfer_t& transfer);
74 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);
75#endif 77#endif
76 78
77 struct FiberImpl; 79 struct FiberImpl;