diff options
| author | 2022-07-02 12:33:49 -0400 | |
|---|---|---|
| committer | 2022-07-02 12:33:49 -0400 | |
| commit | ed0319cfed2c99e6366aaf725d96bb28a9332e4d (patch) | |
| tree | 1598e6d320005e0d177106e28ebc6728234f1f24 /src/tests | |
| parent | Merge pull request #7454 from FernandoS27/new-core-timing (diff) | |
| download | yuzu-ed0319cfed2c99e6366aaf725d96bb28a9332e4d.tar.gz yuzu-ed0319cfed2c99e6366aaf725d96bb28a9332e4d.tar.xz yuzu-ed0319cfed2c99e6366aaf725d96bb28a9332e4d.zip | |
common/fiber: make fibers easier to use
Diffstat (limited to 'src/tests')
| -rw-r--r-- | src/tests/common/fibers.cpp | 123 |
1 files changed, 35 insertions, 88 deletions
diff --git a/src/tests/common/fibers.cpp b/src/tests/common/fibers.cpp index cfc84d423..4e29f9199 100644 --- a/src/tests/common/fibers.cpp +++ b/src/tests/common/fibers.cpp | |||
| @@ -43,7 +43,15 @@ class TestControl1 { | |||
| 43 | public: | 43 | public: |
| 44 | TestControl1() = default; | 44 | TestControl1() = default; |
| 45 | 45 | ||
| 46 | void DoWork(); | 46 | void DoWork() { |
| 47 | const u32 id = thread_ids.Get(); | ||
| 48 | u32 value = items[id]; | ||
| 49 | for (u32 i = 0; i < id; i++) { | ||
| 50 | value++; | ||
| 51 | } | ||
| 52 | results[id] = value; | ||
| 53 | Fiber::YieldTo(work_fibers[id], *thread_fibers[id]); | ||
| 54 | } | ||
| 47 | 55 | ||
| 48 | void ExecuteThread(u32 id); | 56 | void ExecuteThread(u32 id); |
| 49 | 57 | ||
| @@ -54,35 +62,16 @@ public: | |||
| 54 | std::vector<u32> results; | 62 | std::vector<u32> results; |
| 55 | }; | 63 | }; |
| 56 | 64 | ||
| 57 | static void WorkControl1(void* control) { | ||
| 58 | auto* test_control = static_cast<TestControl1*>(control); | ||
| 59 | test_control->DoWork(); | ||
| 60 | } | ||
| 61 | |||
| 62 | void TestControl1::DoWork() { | ||
| 63 | const u32 id = thread_ids.Get(); | ||
| 64 | u32 value = items[id]; | ||
| 65 | for (u32 i = 0; i < id; i++) { | ||
| 66 | value++; | ||
| 67 | } | ||
| 68 | results[id] = value; | ||
| 69 | Fiber::YieldTo(work_fibers[id], *thread_fibers[id]); | ||
| 70 | } | ||
| 71 | |||
| 72 | void TestControl1::ExecuteThread(u32 id) { | 65 | void TestControl1::ExecuteThread(u32 id) { |
| 73 | thread_ids.Register(id); | 66 | thread_ids.Register(id); |
| 74 | auto thread_fiber = Fiber::ThreadToFiber(); | 67 | auto thread_fiber = Fiber::ThreadToFiber(); |
| 75 | thread_fibers[id] = thread_fiber; | 68 | thread_fibers[id] = thread_fiber; |
| 76 | work_fibers[id] = std::make_shared<Fiber>(std::function<void(void*)>{WorkControl1}, this); | 69 | work_fibers[id] = std::make_shared<Fiber>([this] { DoWork(); }); |
| 77 | items[id] = rand() % 256; | 70 | items[id] = rand() % 256; |
| 78 | Fiber::YieldTo(thread_fibers[id], *work_fibers[id]); | 71 | Fiber::YieldTo(thread_fibers[id], *work_fibers[id]); |
| 79 | thread_fibers[id]->Exit(); | 72 | thread_fibers[id]->Exit(); |
| 80 | } | 73 | } |
| 81 | 74 | ||
| 82 | static void ThreadStart1(u32 id, TestControl1& test_control) { | ||
| 83 | test_control.ExecuteThread(id); | ||
| 84 | } | ||
| 85 | |||
| 86 | /** This test checks for fiber setup configuration and validates that fibers are | 75 | /** This test checks for fiber setup configuration and validates that fibers are |
| 87 | * doing all the work required. | 76 | * doing all the work required. |
| 88 | */ | 77 | */ |
| @@ -95,7 +84,7 @@ TEST_CASE("Fibers::Setup", "[common]") { | |||
| 95 | test_control.results.resize(num_threads, 0); | 84 | test_control.results.resize(num_threads, 0); |
| 96 | std::vector<std::thread> threads; | 85 | std::vector<std::thread> threads; |
| 97 | for (u32 i = 0; i < num_threads; i++) { | 86 | for (u32 i = 0; i < num_threads; i++) { |
| 98 | threads.emplace_back(ThreadStart1, i, std::ref(test_control)); | 87 | threads.emplace_back([&test_control, i] { test_control.ExecuteThread(i); }); |
| 99 | } | 88 | } |
| 100 | for (u32 i = 0; i < num_threads; i++) { | 89 | for (u32 i = 0; i < num_threads; i++) { |
| 101 | threads[i].join(); | 90 | threads[i].join(); |
| @@ -167,21 +156,6 @@ public: | |||
| 167 | std::shared_ptr<Common::Fiber> fiber3; | 156 | std::shared_ptr<Common::Fiber> fiber3; |
| 168 | }; | 157 | }; |
| 169 | 158 | ||
| 170 | static void WorkControl2_1(void* control) { | ||
| 171 | auto* test_control = static_cast<TestControl2*>(control); | ||
| 172 | test_control->DoWork1(); | ||
| 173 | } | ||
| 174 | |||
| 175 | static void WorkControl2_2(void* control) { | ||
| 176 | auto* test_control = static_cast<TestControl2*>(control); | ||
| 177 | test_control->DoWork2(); | ||
| 178 | } | ||
| 179 | |||
| 180 | static void WorkControl2_3(void* control) { | ||
| 181 | auto* test_control = static_cast<TestControl2*>(control); | ||
| 182 | test_control->DoWork3(); | ||
| 183 | } | ||
| 184 | |||
| 185 | void TestControl2::ExecuteThread(u32 id) { | 159 | void TestControl2::ExecuteThread(u32 id) { |
| 186 | thread_ids.Register(id); | 160 | thread_ids.Register(id); |
| 187 | auto thread_fiber = Fiber::ThreadToFiber(); | 161 | auto thread_fiber = Fiber::ThreadToFiber(); |
| @@ -193,18 +167,6 @@ void TestControl2::Exit() { | |||
| 193 | thread_fibers[id]->Exit(); | 167 | thread_fibers[id]->Exit(); |
| 194 | } | 168 | } |
| 195 | 169 | ||
| 196 | static void ThreadStart2_1(u32 id, TestControl2& test_control) { | ||
| 197 | test_control.ExecuteThread(id); | ||
| 198 | test_control.CallFiber1(); | ||
| 199 | test_control.Exit(); | ||
| 200 | } | ||
| 201 | |||
| 202 | static void ThreadStart2_2(u32 id, TestControl2& test_control) { | ||
| 203 | test_control.ExecuteThread(id); | ||
| 204 | test_control.CallFiber2(); | ||
| 205 | test_control.Exit(); | ||
| 206 | } | ||
| 207 | |||
| 208 | /** This test checks for fiber thread exchange configuration and validates that fibers are | 170 | /** This test checks for fiber thread exchange configuration and validates that fibers are |
| 209 | * that a fiber has been successfully transferred from one thread to another and that the TLS | 171 | * that a fiber has been successfully transferred from one thread to another and that the TLS |
| 210 | * region of the thread is kept while changing fibers. | 172 | * region of the thread is kept while changing fibers. |
| @@ -212,14 +174,19 @@ static void ThreadStart2_2(u32 id, TestControl2& test_control) { | |||
| 212 | TEST_CASE("Fibers::InterExchange", "[common]") { | 174 | TEST_CASE("Fibers::InterExchange", "[common]") { |
| 213 | TestControl2 test_control{}; | 175 | TestControl2 test_control{}; |
| 214 | test_control.thread_fibers.resize(2); | 176 | test_control.thread_fibers.resize(2); |
| 215 | test_control.fiber1 = | 177 | test_control.fiber1 = std::make_shared<Fiber>([&test_control] { test_control.DoWork1(); }); |
| 216 | std::make_shared<Fiber>(std::function<void(void*)>{WorkControl2_1}, &test_control); | 178 | test_control.fiber2 = std::make_shared<Fiber>([&test_control] { test_control.DoWork2(); }); |
| 217 | test_control.fiber2 = | 179 | test_control.fiber3 = std::make_shared<Fiber>([&test_control] { test_control.DoWork3(); }); |
| 218 | std::make_shared<Fiber>(std::function<void(void*)>{WorkControl2_2}, &test_control); | 180 | std::thread thread1{[&test_control] { |
| 219 | test_control.fiber3 = | 181 | test_control.ExecuteThread(0); |
| 220 | std::make_shared<Fiber>(std::function<void(void*)>{WorkControl2_3}, &test_control); | 182 | test_control.CallFiber1(); |
| 221 | std::thread thread1(ThreadStart2_1, 0, std::ref(test_control)); | 183 | test_control.Exit(); |
| 222 | std::thread thread2(ThreadStart2_2, 1, std::ref(test_control)); | 184 | }}; |
| 185 | std::thread thread2{[&test_control] { | ||
| 186 | test_control.ExecuteThread(1); | ||
| 187 | test_control.CallFiber2(); | ||
| 188 | test_control.Exit(); | ||
| 189 | }}; | ||
| 223 | thread1.join(); | 190 | thread1.join(); |
| 224 | thread2.join(); | 191 | thread2.join(); |
| 225 | REQUIRE(test_control.assert1); | 192 | REQUIRE(test_control.assert1); |
| @@ -270,16 +237,6 @@ public: | |||
| 270 | std::shared_ptr<Common::Fiber> fiber2; | 237 | std::shared_ptr<Common::Fiber> fiber2; |
| 271 | }; | 238 | }; |
| 272 | 239 | ||
| 273 | static void WorkControl3_1(void* control) { | ||
| 274 | auto* test_control = static_cast<TestControl3*>(control); | ||
| 275 | test_control->DoWork1(); | ||
| 276 | } | ||
| 277 | |||
| 278 | static void WorkControl3_2(void* control) { | ||
| 279 | auto* test_control = static_cast<TestControl3*>(control); | ||
| 280 | test_control->DoWork2(); | ||
| 281 | } | ||
| 282 | |||
| 283 | void TestControl3::ExecuteThread(u32 id) { | 240 | void TestControl3::ExecuteThread(u32 id) { |
| 284 | thread_ids.Register(id); | 241 | thread_ids.Register(id); |
| 285 | auto thread_fiber = Fiber::ThreadToFiber(); | 242 | auto thread_fiber = Fiber::ThreadToFiber(); |
| @@ -291,12 +248,6 @@ void TestControl3::Exit() { | |||
| 291 | thread_fibers[id]->Exit(); | 248 | thread_fibers[id]->Exit(); |
| 292 | } | 249 | } |
| 293 | 250 | ||
| 294 | static void ThreadStart3(u32 id, TestControl3& test_control) { | ||
| 295 | test_control.ExecuteThread(id); | ||
| 296 | test_control.CallFiber1(); | ||
| 297 | test_control.Exit(); | ||
| 298 | } | ||
| 299 | |||
| 300 | /** This test checks for one two threads racing for starting the same fiber. | 251 | /** This test checks for one two threads racing for starting the same fiber. |
| 301 | * It checks execution occurred in an ordered manner and by no time there were | 252 | * It checks execution occurred in an ordered manner and by no time there were |
| 302 | * two contexts at the same time. | 253 | * two contexts at the same time. |
| @@ -304,12 +255,15 @@ static void ThreadStart3(u32 id, TestControl3& test_control) { | |||
| 304 | TEST_CASE("Fibers::StartRace", "[common]") { | 255 | TEST_CASE("Fibers::StartRace", "[common]") { |
| 305 | TestControl3 test_control{}; | 256 | TestControl3 test_control{}; |
| 306 | test_control.thread_fibers.resize(2); | 257 | test_control.thread_fibers.resize(2); |
| 307 | test_control.fiber1 = | 258 | test_control.fiber1 = std::make_shared<Fiber>([&test_control] { test_control.DoWork1(); }); |
| 308 | std::make_shared<Fiber>(std::function<void(void*)>{WorkControl3_1}, &test_control); | 259 | test_control.fiber2 = std::make_shared<Fiber>([&test_control] { test_control.DoWork2(); }); |
| 309 | test_control.fiber2 = | 260 | const auto race_function{[&test_control](u32 id) { |
| 310 | std::make_shared<Fiber>(std::function<void(void*)>{WorkControl3_2}, &test_control); | 261 | test_control.ExecuteThread(id); |
| 311 | std::thread thread1(ThreadStart3, 0, std::ref(test_control)); | 262 | test_control.CallFiber1(); |
| 312 | std::thread thread2(ThreadStart3, 1, std::ref(test_control)); | 263 | test_control.Exit(); |
| 264 | }}; | ||
| 265 | std::thread thread1([&] { race_function(0); }); | ||
| 266 | std::thread thread2([&] { race_function(1); }); | ||
| 313 | thread1.join(); | 267 | thread1.join(); |
| 314 | thread2.join(); | 268 | thread2.join(); |
| 315 | REQUIRE(test_control.value1 == 1); | 269 | REQUIRE(test_control.value1 == 1); |
| @@ -319,12 +273,10 @@ TEST_CASE("Fibers::StartRace", "[common]") { | |||
| 319 | 273 | ||
| 320 | class TestControl4; | 274 | class TestControl4; |
| 321 | 275 | ||
| 322 | static void WorkControl4(void* control); | ||
| 323 | |||
| 324 | class TestControl4 { | 276 | class TestControl4 { |
| 325 | public: | 277 | public: |
| 326 | TestControl4() { | 278 | TestControl4() { |
| 327 | fiber1 = std::make_shared<Fiber>(std::function<void(void*)>{WorkControl4}, this); | 279 | fiber1 = std::make_shared<Fiber>([this] { DoWork(); }); |
| 328 | goal_reached = false; | 280 | goal_reached = false; |
| 329 | rewinded = false; | 281 | rewinded = false; |
| 330 | } | 282 | } |
| @@ -336,7 +288,7 @@ public: | |||
| 336 | } | 288 | } |
| 337 | 289 | ||
| 338 | void DoWork() { | 290 | void DoWork() { |
| 339 | fiber1->SetRewindPoint(std::function<void(void*)>{WorkControl4}, this); | 291 | fiber1->SetRewindPoint([this] { DoWork(); }); |
| 340 | if (rewinded) { | 292 | if (rewinded) { |
| 341 | goal_reached = true; | 293 | goal_reached = true; |
| 342 | Fiber::YieldTo(fiber1, *thread_fiber); | 294 | Fiber::YieldTo(fiber1, *thread_fiber); |
| @@ -351,11 +303,6 @@ public: | |||
| 351 | bool rewinded; | 303 | bool rewinded; |
| 352 | }; | 304 | }; |
| 353 | 305 | ||
| 354 | static void WorkControl4(void* control) { | ||
| 355 | auto* test_control = static_cast<TestControl4*>(control); | ||
| 356 | test_control->DoWork(); | ||
| 357 | } | ||
| 358 | |||
| 359 | TEST_CASE("Fibers::Rewind", "[common]") { | 306 | TEST_CASE("Fibers::Rewind", "[common]") { |
| 360 | TestControl4 test_control{}; | 307 | TestControl4 test_control{}; |
| 361 | test_control.Execute(); | 308 | test_control.Execute(); |