summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar Lioncash2020-11-06 20:29:54 -0500
committerGravatar Lioncash2020-11-06 20:36:32 -0500
commit00fb79b2f3f49335543c57f1d27b057320f3ff05 (patch)
tree6a92120ea5b1c063165a295d2a8814c649522e9f /src
parentMerge pull request #4891 from lioncash/clang2 (diff)
downloadyuzu-00fb79b2f3f49335543c57f1d27b057320f3ff05.tar.gz
yuzu-00fb79b2f3f49335543c57f1d27b057320f3ff05.tar.xz
yuzu-00fb79b2f3f49335543c57f1d27b057320f3ff05.zip
common/fiber: Move all member variables into impl class
Hides all of the implementation details for users of the class. This has the benefit of reducing includes and also making the fiber classes movable again.
Diffstat (limited to '')
-rw-r--r--src/common/fiber.cpp155
-rw-r--r--src/common/fiber.h20
2 files changed, 86 insertions, 89 deletions
diff --git a/src/common/fiber.cpp b/src/common/fiber.cpp
index b209f52fc..3e3029cd1 100644
--- a/src/common/fiber.cpp
+++ b/src/common/fiber.cpp
@@ -4,6 +4,8 @@
4 4
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"
8
7#if defined(_WIN32) || defined(WIN32) 9#if defined(_WIN32) || defined(WIN32)
8#include <windows.h> 10#include <windows.h>
9#else 11#else
@@ -14,18 +16,45 @@ namespace Common {
14 16
15constexpr std::size_t default_stack_size = 256 * 1024; // 256kb 17constexpr std::size_t default_stack_size = 256 * 1024; // 256kb
16 18
17#if defined(_WIN32) || defined(WIN32)
18
19struct Fiber::FiberImpl { 19struct Fiber::FiberImpl {
20 SpinLock guard{};
21 std::function<void(void*)> entry_point;
22 std::function<void(void*)> rewind_point;
23 void* rewind_parameter{};
24 void* start_parameter{};
25 std::shared_ptr<Fiber> previous_fiber;
26 bool is_thread_fiber{};
27 bool released{};
28
29#if defined(_WIN32) || defined(WIN32)
20 LPVOID handle = nullptr; 30 LPVOID handle = nullptr;
21 LPVOID rewind_handle = nullptr; 31 LPVOID rewind_handle = nullptr;
32#else
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
22}; 40};
23 41
42void Fiber::SetStartParameter(void* new_parameter) {
43 impl->start_parameter = new_parameter;
44}
45
46void Fiber::SetRewindPoint(std::function<void(void*)>&& rewind_func, void* rewind_param) {
47 impl->rewind_point = std::move(rewind_func);
48 impl->rewind_parameter = rewind_param;
49}
50
51#if defined(_WIN32) || defined(WIN32)
52
24void Fiber::Start() { 53void Fiber::Start() {
25 ASSERT(previous_fiber != nullptr); 54 ASSERT(impl->previous_fiber != nullptr);
26 previous_fiber->guard.unlock(); 55 impl->previous_fiber->impl->guard.unlock();
27 previous_fiber.reset(); 56 impl->previous_fiber.reset();
28 entry_point(start_parameter); 57 impl->entry_point(impl->start_parameter);
29 UNREACHABLE(); 58 UNREACHABLE();
30} 59}
31 60
@@ -34,58 +63,54 @@ void Fiber::OnRewind() {
34 DeleteFiber(impl->handle); 63 DeleteFiber(impl->handle);
35 impl->handle = impl->rewind_handle; 64 impl->handle = impl->rewind_handle;
36 impl->rewind_handle = nullptr; 65 impl->rewind_handle = nullptr;
37 rewind_point(rewind_parameter); 66 impl->rewind_point(impl->rewind_parameter);
38 UNREACHABLE(); 67 UNREACHABLE();
39} 68}
40 69
41void Fiber::FiberStartFunc(void* fiber_parameter) { 70void Fiber::FiberStartFunc(void* fiber_parameter) {
42 auto fiber = static_cast<Fiber*>(fiber_parameter); 71 auto* fiber = static_cast<Fiber*>(fiber_parameter);
43 fiber->Start(); 72 fiber->Start();
44} 73}
45 74
46void Fiber::RewindStartFunc(void* fiber_parameter) { 75void Fiber::RewindStartFunc(void* fiber_parameter) {
47 auto fiber = static_cast<Fiber*>(fiber_parameter); 76 auto* fiber = static_cast<Fiber*>(fiber_parameter);
48 fiber->OnRewind(); 77 fiber->OnRewind();
49} 78}
50 79
51Fiber::Fiber(std::function<void(void*)>&& entry_point_func, void* start_parameter) 80Fiber::Fiber(std::function<void(void*)>&& entry_point_func, void* start_parameter)
52 : entry_point{std::move(entry_point_func)}, start_parameter{start_parameter} { 81 : impl{std::make_unique<FiberImpl>()} {
53 impl = std::make_unique<FiberImpl>(); 82 impl->entry_point = std::move(entry_point_func);
83 impl->start_parameter = start_parameter;
54 impl->handle = CreateFiber(default_stack_size, &FiberStartFunc, this); 84 impl->handle = CreateFiber(default_stack_size, &FiberStartFunc, this);
55} 85}
56 86
57Fiber::Fiber() : impl{std::make_unique<FiberImpl>()} {} 87Fiber::Fiber() : impl{std::make_unique<FiberImpl>()} {}
58 88
59Fiber::~Fiber() { 89Fiber::~Fiber() {
60 if (released) { 90 if (impl->released) {
61 return; 91 return;
62 } 92 }
63 // Make sure the Fiber is not being used 93 // Make sure the Fiber is not being used
64 const bool locked = guard.try_lock(); 94 const bool locked = impl->guard.try_lock();
65 ASSERT_MSG(locked, "Destroying a fiber that's still running"); 95 ASSERT_MSG(locked, "Destroying a fiber that's still running");
66 if (locked) { 96 if (locked) {
67 guard.unlock(); 97 impl->guard.unlock();
68 } 98 }
69 DeleteFiber(impl->handle); 99 DeleteFiber(impl->handle);
70} 100}
71 101
72void Fiber::Exit() { 102void Fiber::Exit() {
73 ASSERT_MSG(is_thread_fiber, "Exitting non main thread fiber"); 103 ASSERT_MSG(impl->is_thread_fiber, "Exitting non main thread fiber");
74 if (!is_thread_fiber) { 104 if (!impl->is_thread_fiber) {
75 return; 105 return;
76 } 106 }
77 ConvertFiberToThread(); 107 ConvertFiberToThread();
78 guard.unlock(); 108 impl->guard.unlock();
79 released = true; 109 impl->released = true;
80}
81
82void Fiber::SetRewindPoint(std::function<void(void*)>&& rewind_func, void* rewind_param) {
83 rewind_point = std::move(rewind_func);
84 rewind_parameter = rewind_param;
85} 110}
86 111
87void Fiber::Rewind() { 112void Fiber::Rewind() {
88 ASSERT(rewind_point); 113 ASSERT(impl->rewind_point);
89 ASSERT(impl->rewind_handle == nullptr); 114 ASSERT(impl->rewind_handle == nullptr);
90 impl->rewind_handle = CreateFiber(default_stack_size, &RewindStartFunc, this); 115 impl->rewind_handle = CreateFiber(default_stack_size, &RewindStartFunc, this);
91 SwitchToFiber(impl->rewind_handle); 116 SwitchToFiber(impl->rewind_handle);
@@ -94,39 +119,30 @@ void Fiber::Rewind() {
94void Fiber::YieldTo(std::shared_ptr<Fiber> from, std::shared_ptr<Fiber> to) { 119void Fiber::YieldTo(std::shared_ptr<Fiber> from, std::shared_ptr<Fiber> to) {
95 ASSERT_MSG(from != nullptr, "Yielding fiber is null!"); 120 ASSERT_MSG(from != nullptr, "Yielding fiber is null!");
96 ASSERT_MSG(to != nullptr, "Next fiber is null!"); 121 ASSERT_MSG(to != nullptr, "Next fiber is null!");
97 to->guard.lock(); 122 to->impl->guard.lock();
98 to->previous_fiber = from; 123 to->impl->previous_fiber = from;
99 SwitchToFiber(to->impl->handle); 124 SwitchToFiber(to->impl->handle);
100 ASSERT(from->previous_fiber != nullptr); 125 ASSERT(from->impl->previous_fiber != nullptr);
101 from->previous_fiber->guard.unlock(); 126 from->impl->previous_fiber->impl->guard.unlock();
102 from->previous_fiber.reset(); 127 from->impl->previous_fiber.reset();
103} 128}
104 129
105std::shared_ptr<Fiber> Fiber::ThreadToFiber() { 130std::shared_ptr<Fiber> Fiber::ThreadToFiber() {
106 std::shared_ptr<Fiber> fiber = std::shared_ptr<Fiber>{new Fiber()}; 131 std::shared_ptr<Fiber> fiber = std::shared_ptr<Fiber>{new Fiber()};
107 fiber->guard.lock(); 132 fiber->impl->guard.lock();
108 fiber->impl->handle = ConvertThreadToFiber(nullptr); 133 fiber->impl->handle = ConvertThreadToFiber(nullptr);
109 fiber->is_thread_fiber = true; 134 fiber->impl->is_thread_fiber = true;
110 return fiber; 135 return fiber;
111} 136}
112 137
113#else 138#else
114 139
115struct Fiber::FiberImpl {
116 alignas(64) std::array<u8, default_stack_size> stack;
117 alignas(64) std::array<u8, default_stack_size> rewind_stack;
118 u8* stack_limit;
119 u8* rewind_stack_limit;
120 boost::context::detail::fcontext_t context;
121 boost::context::detail::fcontext_t rewind_context;
122};
123
124void Fiber::Start(boost::context::detail::transfer_t& transfer) { 140void Fiber::Start(boost::context::detail::transfer_t& transfer) {
125 ASSERT(previous_fiber != nullptr); 141 ASSERT(impl->previous_fiber != nullptr);
126 previous_fiber->impl->context = transfer.fctx; 142 impl->previous_fiber->impl->context = transfer.fctx;
127 previous_fiber->guard.unlock(); 143 impl->previous_fiber->impl->guard.unlock();
128 previous_fiber.reset(); 144 impl->previous_fiber.reset();
129 entry_point(start_parameter); 145 impl->entry_point(impl->start_parameter);
130 UNREACHABLE(); 146 UNREACHABLE();
131} 147}
132 148
@@ -137,23 +153,24 @@ void Fiber::OnRewind([[maybe_unused]] boost::context::detail::transfer_t& transf
137 u8* tmp = impl->stack_limit; 153 u8* tmp = impl->stack_limit;
138 impl->stack_limit = impl->rewind_stack_limit; 154 impl->stack_limit = impl->rewind_stack_limit;
139 impl->rewind_stack_limit = tmp; 155 impl->rewind_stack_limit = tmp;
140 rewind_point(rewind_parameter); 156 impl->rewind_point(impl->rewind_parameter);
141 UNREACHABLE(); 157 UNREACHABLE();
142} 158}
143 159
144void Fiber::FiberStartFunc(boost::context::detail::transfer_t transfer) { 160void Fiber::FiberStartFunc(boost::context::detail::transfer_t transfer) {
145 auto fiber = static_cast<Fiber*>(transfer.data); 161 auto* fiber = static_cast<Fiber*>(transfer.data);
146 fiber->Start(transfer); 162 fiber->Start(transfer);
147} 163}
148 164
149void Fiber::RewindStartFunc(boost::context::detail::transfer_t transfer) { 165void Fiber::RewindStartFunc(boost::context::detail::transfer_t transfer) {
150 auto fiber = static_cast<Fiber*>(transfer.data); 166 auto* fiber = static_cast<Fiber*>(transfer.data);
151 fiber->OnRewind(transfer); 167 fiber->OnRewind(transfer);
152} 168}
153 169
154Fiber::Fiber(std::function<void(void*)>&& entry_point_func, void* start_parameter) 170Fiber::Fiber(std::function<void(void*)>&& entry_point_func, void* start_parameter)
155 : entry_point{std::move(entry_point_func)}, start_parameter{start_parameter} { 171 : impl{std::make_unique<FiberImpl>()} {
156 impl = std::make_unique<FiberImpl>(); 172 impl->entry_point = std::move(entry_point_func);
173 impl->start_parameter = start_parameter;
157 impl->stack_limit = impl->stack.data(); 174 impl->stack_limit = impl->stack.data();
158 impl->rewind_stack_limit = impl->rewind_stack.data(); 175 impl->rewind_stack_limit = impl->rewind_stack.data();
159 u8* stack_base = impl->stack_limit + default_stack_size; 176 u8* stack_base = impl->stack_limit + default_stack_size;
@@ -161,37 +178,31 @@ Fiber::Fiber(std::function<void(void*)>&& entry_point_func, void* start_paramete
161 boost::context::detail::make_fcontext(stack_base, impl->stack.size(), FiberStartFunc); 178 boost::context::detail::make_fcontext(stack_base, impl->stack.size(), FiberStartFunc);
162} 179}
163 180
164void Fiber::SetRewindPoint(std::function<void(void*)>&& rewind_func, void* rewind_param) {
165 rewind_point = std::move(rewind_func);
166 rewind_parameter = rewind_param;
167}
168
169Fiber::Fiber() : impl{std::make_unique<FiberImpl>()} {} 181Fiber::Fiber() : impl{std::make_unique<FiberImpl>()} {}
170 182
171Fiber::~Fiber() { 183Fiber::~Fiber() {
172 if (released) { 184 if (impl->released) {
173 return; 185 return;
174 } 186 }
175 // Make sure the Fiber is not being used 187 // Make sure the Fiber is not being used
176 const bool locked = guard.try_lock(); 188 const bool locked = impl->guard.try_lock();
177 ASSERT_MSG(locked, "Destroying a fiber that's still running"); 189 ASSERT_MSG(locked, "Destroying a fiber that's still running");
178 if (locked) { 190 if (locked) {
179 guard.unlock(); 191 impl->guard.unlock();
180 } 192 }
181} 193}
182 194
183void Fiber::Exit() { 195void Fiber::Exit() {
184 196 ASSERT_MSG(impl->is_thread_fiber, "Exitting non main thread fiber");
185 ASSERT_MSG(is_thread_fiber, "Exitting non main thread fiber"); 197 if (!impl->is_thread_fiber) {
186 if (!is_thread_fiber) {
187 return; 198 return;
188 } 199 }
189 guard.unlock(); 200 impl->guard.unlock();
190 released = true; 201 impl->released = true;
191} 202}
192 203
193void Fiber::Rewind() { 204void Fiber::Rewind() {
194 ASSERT(rewind_point); 205 ASSERT(impl->rewind_point);
195 ASSERT(impl->rewind_context == nullptr); 206 ASSERT(impl->rewind_context == nullptr);
196 u8* stack_base = impl->rewind_stack_limit + default_stack_size; 207 u8* stack_base = impl->rewind_stack_limit + default_stack_size;
197 impl->rewind_context = 208 impl->rewind_context =
@@ -202,19 +213,19 @@ void Fiber::Rewind() {
202void Fiber::YieldTo(std::shared_ptr<Fiber> from, std::shared_ptr<Fiber> to) { 213void Fiber::YieldTo(std::shared_ptr<Fiber> from, std::shared_ptr<Fiber> to) {
203 ASSERT_MSG(from != nullptr, "Yielding fiber is null!"); 214 ASSERT_MSG(from != nullptr, "Yielding fiber is null!");
204 ASSERT_MSG(to != nullptr, "Next fiber is null!"); 215 ASSERT_MSG(to != nullptr, "Next fiber is null!");
205 to->guard.lock(); 216 to->impl->guard.lock();
206 to->previous_fiber = from; 217 to->impl->previous_fiber = from;
207 auto transfer = boost::context::detail::jump_fcontext(to->impl->context, to.get()); 218 auto transfer = boost::context::detail::jump_fcontext(to->impl->context, to.get());
208 ASSERT(from->previous_fiber != nullptr); 219 ASSERT(from->impl->previous_fiber != nullptr);
209 from->previous_fiber->impl->context = transfer.fctx; 220 from->impl->previous_fiber->impl->context = transfer.fctx;
210 from->previous_fiber->guard.unlock(); 221 from->impl->previous_fiber->impl->guard.unlock();
211 from->previous_fiber.reset(); 222 from->impl->previous_fiber.reset();
212} 223}
213 224
214std::shared_ptr<Fiber> Fiber::ThreadToFiber() { 225std::shared_ptr<Fiber> Fiber::ThreadToFiber() {
215 std::shared_ptr<Fiber> fiber = std::shared_ptr<Fiber>{new Fiber()}; 226 std::shared_ptr<Fiber> fiber = std::shared_ptr<Fiber>{new Fiber()};
216 fiber->guard.lock(); 227 fiber->impl->guard.lock();
217 fiber->is_thread_fiber = true; 228 fiber->impl->is_thread_fiber = true;
218 return fiber; 229 return fiber;
219} 230}
220 231
diff --git a/src/common/fiber.h b/src/common/fiber.h
index 1a027be96..5323e8579 100644
--- a/src/common/fiber.h
+++ b/src/common/fiber.h
@@ -7,9 +7,6 @@
7#include <functional> 7#include <functional>
8#include <memory> 8#include <memory>
9 9
10#include "common/common_types.h"
11#include "common/spin_lock.h"
12
13#if !defined(_WIN32) && !defined(WIN32) 10#if !defined(_WIN32) && !defined(WIN32)
14namespace boost::context::detail { 11namespace boost::context::detail {
15struct transfer_t; 12struct transfer_t;
@@ -41,8 +38,8 @@ public:
41 Fiber(const Fiber&) = delete; 38 Fiber(const Fiber&) = delete;
42 Fiber& operator=(const Fiber&) = delete; 39 Fiber& operator=(const Fiber&) = delete;
43 40
44 Fiber(Fiber&&) = delete; 41 Fiber(Fiber&&) = default;
45 Fiber& operator=(Fiber&&) = delete; 42 Fiber& operator=(Fiber&&) = default;
46 43
47 /// Yields control from Fiber 'from' to Fiber 'to' 44 /// Yields control from Fiber 'from' to Fiber 'to'
48 /// Fiber 'from' must be the currently running fiber. 45 /// Fiber 'from' must be the currently running fiber.
@@ -57,9 +54,7 @@ public:
57 void Exit(); 54 void Exit();
58 55
59 /// Changes the start parameter of the fiber. Has no effect if the fiber already started 56 /// Changes the start parameter of the fiber. Has no effect if the fiber already started
60 void SetStartParameter(void* new_parameter) { 57 void SetStartParameter(void* new_parameter);
61 start_parameter = new_parameter;
62 }
63 58
64private: 59private:
65 Fiber(); 60 Fiber();
@@ -77,16 +72,7 @@ private:
77#endif 72#endif
78 73
79 struct FiberImpl; 74 struct FiberImpl;
80
81 SpinLock guard{};
82 std::function<void(void*)> entry_point;
83 std::function<void(void*)> rewind_point;
84 void* rewind_parameter{};
85 void* start_parameter{};
86 std::shared_ptr<Fiber> previous_fiber;
87 std::unique_ptr<FiberImpl> impl; 75 std::unique_ptr<FiberImpl> impl;
88 bool is_thread_fiber{};
89 bool released{};
90}; 76};
91 77
92} // namespace Common 78} // namespace Common