diff options
| author | 2021-02-27 11:56:04 -0800 | |
|---|---|---|
| committer | 2021-02-27 11:56:04 -0800 | |
| commit | 51fb0a6f9647ba199da10fe4f018ee36e44e65ba (patch) | |
| tree | 89cd2ad6dfb310587aa546bb7b9847762795f08f /src | |
| parent | Merge pull request #5953 from bunnei/memory-refactor-1 (diff) | |
| download | yuzu-51fb0a6f9647ba199da10fe4f018ee36e44e65ba.tar.gz yuzu-51fb0a6f9647ba199da10fe4f018ee36e44e65ba.tar.xz yuzu-51fb0a6f9647ba199da10fe4f018ee36e44e65ba.zip | |
core: Switch to unique_ptr for usage of Common::Fiber.
- With using unique_ptr instead of shared_ptr, we have more explicit ownership of the context.
- Fixes a memory leak due to circular reference of the shared pointer.
Diffstat (limited to 'src')
| -rw-r--r-- | src/common/fiber.cpp | 14 | ||||
| -rw-r--r-- | src/common/fiber.h | 4 | ||||
| -rw-r--r-- | src/core/cpu_manager.cpp | 11 | ||||
| -rw-r--r-- | src/core/cpu_manager.h | 2 | ||||
| -rw-r--r-- | src/core/hle/kernel/k_scheduler.cpp | 18 | ||||
| -rw-r--r-- | src/core/hle/kernel/k_scheduler.h | 10 | ||||
| -rw-r--r-- | src/core/hle/kernel/k_thread.cpp | 6 | ||||
| -rw-r--r-- | src/core/hle/kernel/k_thread.h | 10 | ||||
| -rw-r--r-- | src/core/hle/kernel/svc.cpp | 3 | ||||
| -rw-r--r-- | src/tests/common/fibers.cpp | 39 |
10 files changed, 58 insertions, 59 deletions
diff --git a/src/common/fiber.cpp b/src/common/fiber.cpp index 3c1eefcb7..b8e98b12a 100644 --- a/src/common/fiber.cpp +++ b/src/common/fiber.cpp | |||
| @@ -24,7 +24,7 @@ struct Fiber::FiberImpl { | |||
| 24 | std::function<void(void*)> rewind_point; | 24 | std::function<void(void*)> rewind_point; |
| 25 | void* rewind_parameter{}; | 25 | void* rewind_parameter{}; |
| 26 | void* start_parameter{}; | 26 | void* start_parameter{}; |
| 27 | std::shared_ptr<Fiber> previous_fiber; | 27 | Fiber* previous_fiber; |
| 28 | bool is_thread_fiber{}; | 28 | bool is_thread_fiber{}; |
| 29 | bool released{}; | 29 | bool released{}; |
| 30 | 30 | ||
| @@ -47,7 +47,7 @@ void Fiber::Start(boost::context::detail::transfer_t& transfer) { | |||
| 47 | ASSERT(impl->previous_fiber != nullptr); | 47 | ASSERT(impl->previous_fiber != nullptr); |
| 48 | impl->previous_fiber->impl->context = transfer.fctx; | 48 | impl->previous_fiber->impl->context = transfer.fctx; |
| 49 | impl->previous_fiber->impl->guard.unlock(); | 49 | impl->previous_fiber->impl->guard.unlock(); |
| 50 | impl->previous_fiber.reset(); | 50 | impl->previous_fiber = nullptr; |
| 51 | impl->entry_point(impl->start_parameter); | 51 | impl->entry_point(impl->start_parameter); |
| 52 | UNREACHABLE(); | 52 | UNREACHABLE(); |
| 53 | } | 53 | } |
| @@ -116,20 +116,20 @@ void Fiber::Rewind() { | |||
| 116 | boost::context::detail::jump_fcontext(impl->rewind_context, this); | 116 | boost::context::detail::jump_fcontext(impl->rewind_context, this); |
| 117 | } | 117 | } |
| 118 | 118 | ||
| 119 | void Fiber::YieldTo(std::shared_ptr<Fiber> from, std::shared_ptr<Fiber> to) { | 119 | void Fiber::YieldTo(Fiber* from, Fiber* to) { |
| 120 | ASSERT_MSG(from != nullptr, "Yielding fiber is null!"); | 120 | ASSERT_MSG(from != nullptr, "Yielding fiber is null!"); |
| 121 | ASSERT_MSG(to != nullptr, "Next fiber is null!"); | 121 | ASSERT_MSG(to != nullptr, "Next fiber is null!"); |
| 122 | to->impl->guard.lock(); | 122 | to->impl->guard.lock(); |
| 123 | to->impl->previous_fiber = from; | 123 | to->impl->previous_fiber = from; |
| 124 | auto transfer = boost::context::detail::jump_fcontext(to->impl->context, to.get()); | 124 | auto transfer = boost::context::detail::jump_fcontext(to->impl->context, to); |
| 125 | ASSERT(from->impl->previous_fiber != nullptr); | 125 | ASSERT(from->impl->previous_fiber != nullptr); |
| 126 | from->impl->previous_fiber->impl->context = transfer.fctx; | 126 | from->impl->previous_fiber->impl->context = transfer.fctx; |
| 127 | from->impl->previous_fiber->impl->guard.unlock(); | 127 | from->impl->previous_fiber->impl->guard.unlock(); |
| 128 | from->impl->previous_fiber.reset(); | 128 | from->impl->previous_fiber = nullptr; |
| 129 | } | 129 | } |
| 130 | 130 | ||
| 131 | std::shared_ptr<Fiber> Fiber::ThreadToFiber() { | 131 | std::unique_ptr<Fiber> Fiber::ThreadToFiber() { |
| 132 | std::shared_ptr<Fiber> fiber = std::shared_ptr<Fiber>{new Fiber()}; | 132 | std::unique_ptr<Fiber> fiber = std::unique_ptr<Fiber>{new Fiber()}; |
| 133 | fiber->impl->guard.lock(); | 133 | fiber->impl->guard.lock(); |
| 134 | fiber->impl->is_thread_fiber = true; | 134 | fiber->impl->is_thread_fiber = true; |
| 135 | return fiber; | 135 | return fiber; |
diff --git a/src/common/fiber.h b/src/common/fiber.h index f7f587f8c..6924f7996 100644 --- a/src/common/fiber.h +++ b/src/common/fiber.h | |||
| @@ -41,8 +41,8 @@ public: | |||
| 41 | 41 | ||
| 42 | /// Yields control from Fiber 'from' to Fiber 'to' | 42 | /// Yields control from Fiber 'from' to Fiber 'to' |
| 43 | /// Fiber 'from' must be the currently running fiber. | 43 | /// Fiber 'from' must be the currently running fiber. |
| 44 | static void YieldTo(std::shared_ptr<Fiber> from, std::shared_ptr<Fiber> to); | 44 | static void YieldTo(Fiber* from, Fiber* to); |
| 45 | [[nodiscard]] static std::shared_ptr<Fiber> ThreadToFiber(); | 45 | [[nodiscard]] static std::unique_ptr<Fiber> ThreadToFiber(); |
| 46 | 46 | ||
| 47 | void SetRewindPoint(std::function<void(void*)>&& rewind_func, void* rewind_param); | 47 | void SetRewindPoint(std::function<void(void*)>&& rewind_func, void* rewind_param); |
| 48 | 48 | ||
diff --git a/src/core/cpu_manager.cpp b/src/core/cpu_manager.cpp index 8f04fb8f5..c35438c6f 100644 --- a/src/core/cpu_manager.cpp +++ b/src/core/cpu_manager.cpp | |||
| @@ -111,7 +111,7 @@ void CpuManager::MultiCoreRunGuestThread() { | |||
| 111 | auto& kernel = system.Kernel(); | 111 | auto& kernel = system.Kernel(); |
| 112 | kernel.CurrentScheduler()->OnThreadStart(); | 112 | kernel.CurrentScheduler()->OnThreadStart(); |
| 113 | auto* thread = kernel.CurrentScheduler()->GetCurrentThread(); | 113 | auto* thread = kernel.CurrentScheduler()->GetCurrentThread(); |
| 114 | auto& host_context = thread->GetHostContext(); | 114 | auto host_context = thread->GetHostContext(); |
| 115 | host_context->SetRewindPoint(GuestRewindFunction, this); | 115 | host_context->SetRewindPoint(GuestRewindFunction, this); |
| 116 | MultiCoreRunGuestLoop(); | 116 | MultiCoreRunGuestLoop(); |
| 117 | } | 117 | } |
| @@ -148,7 +148,8 @@ void CpuManager::MultiCoreRunSuspendThread() { | |||
| 148 | auto core = kernel.GetCurrentHostThreadID(); | 148 | auto core = kernel.GetCurrentHostThreadID(); |
| 149 | auto& scheduler = *kernel.CurrentScheduler(); | 149 | auto& scheduler = *kernel.CurrentScheduler(); |
| 150 | Kernel::KThread* current_thread = scheduler.GetCurrentThread(); | 150 | Kernel::KThread* current_thread = scheduler.GetCurrentThread(); |
| 151 | Common::Fiber::YieldTo(current_thread->GetHostContext(), core_data[core].host_context); | 151 | Common::Fiber::YieldTo(current_thread->GetHostContext(), |
| 152 | core_data[core].host_context.get()); | ||
| 152 | ASSERT(scheduler.ContextSwitchPending()); | 153 | ASSERT(scheduler.ContextSwitchPending()); |
| 153 | ASSERT(core == kernel.GetCurrentHostThreadID()); | 154 | ASSERT(core == kernel.GetCurrentHostThreadID()); |
| 154 | scheduler.RescheduleCurrentCore(); | 155 | scheduler.RescheduleCurrentCore(); |
| @@ -201,7 +202,7 @@ void CpuManager::SingleCoreRunGuestThread() { | |||
| 201 | auto& kernel = system.Kernel(); | 202 | auto& kernel = system.Kernel(); |
| 202 | kernel.CurrentScheduler()->OnThreadStart(); | 203 | kernel.CurrentScheduler()->OnThreadStart(); |
| 203 | auto* thread = kernel.CurrentScheduler()->GetCurrentThread(); | 204 | auto* thread = kernel.CurrentScheduler()->GetCurrentThread(); |
| 204 | auto& host_context = thread->GetHostContext(); | 205 | auto host_context = thread->GetHostContext(); |
| 205 | host_context->SetRewindPoint(GuestRewindFunction, this); | 206 | host_context->SetRewindPoint(GuestRewindFunction, this); |
| 206 | SingleCoreRunGuestLoop(); | 207 | SingleCoreRunGuestLoop(); |
| 207 | } | 208 | } |
| @@ -245,7 +246,7 @@ void CpuManager::SingleCoreRunSuspendThread() { | |||
| 245 | auto core = kernel.GetCurrentHostThreadID(); | 246 | auto core = kernel.GetCurrentHostThreadID(); |
| 246 | auto& scheduler = *kernel.CurrentScheduler(); | 247 | auto& scheduler = *kernel.CurrentScheduler(); |
| 247 | Kernel::KThread* current_thread = scheduler.GetCurrentThread(); | 248 | Kernel::KThread* current_thread = scheduler.GetCurrentThread(); |
| 248 | Common::Fiber::YieldTo(current_thread->GetHostContext(), core_data[0].host_context); | 249 | Common::Fiber::YieldTo(current_thread->GetHostContext(), core_data[0].host_context.get()); |
| 249 | ASSERT(scheduler.ContextSwitchPending()); | 250 | ASSERT(scheduler.ContextSwitchPending()); |
| 250 | ASSERT(core == kernel.GetCurrentHostThreadID()); | 251 | ASSERT(core == kernel.GetCurrentHostThreadID()); |
| 251 | scheduler.RescheduleCurrentCore(); | 252 | scheduler.RescheduleCurrentCore(); |
| @@ -363,7 +364,7 @@ void CpuManager::RunThread(std::size_t core) { | |||
| 363 | 364 | ||
| 364 | auto current_thread = system.Kernel().CurrentScheduler()->GetCurrentThread(); | 365 | auto current_thread = system.Kernel().CurrentScheduler()->GetCurrentThread(); |
| 365 | data.is_running = true; | 366 | data.is_running = true; |
| 366 | Common::Fiber::YieldTo(data.host_context, current_thread->GetHostContext()); | 367 | Common::Fiber::YieldTo(data.host_context.get(), current_thread->GetHostContext()); |
| 367 | data.is_running = false; | 368 | data.is_running = false; |
| 368 | data.is_paused = true; | 369 | data.is_paused = true; |
| 369 | data.exit_barrier->Wait(); | 370 | data.exit_barrier->Wait(); |
diff --git a/src/core/cpu_manager.h b/src/core/cpu_manager.h index 17420c941..5ea149f1f 100644 --- a/src/core/cpu_manager.h +++ b/src/core/cpu_manager.h | |||
| @@ -83,7 +83,7 @@ private: | |||
| 83 | void RunThread(std::size_t core); | 83 | void RunThread(std::size_t core); |
| 84 | 84 | ||
| 85 | struct CoreData { | 85 | struct CoreData { |
| 86 | std::shared_ptr<Common::Fiber> host_context; | 86 | std::unique_ptr<Common::Fiber> host_context; |
| 87 | std::unique_ptr<Common::Event> enter_barrier; | 87 | std::unique_ptr<Common::Event> enter_barrier; |
| 88 | std::unique_ptr<Common::Event> exit_barrier; | 88 | std::unique_ptr<Common::Event> exit_barrier; |
| 89 | std::atomic<bool> is_running; | 89 | std::atomic<bool> is_running; |
diff --git a/src/core/hle/kernel/k_scheduler.cpp b/src/core/hle/kernel/k_scheduler.cpp index bb5f43b53..465036f3d 100644 --- a/src/core/hle/kernel/k_scheduler.cpp +++ b/src/core/hle/kernel/k_scheduler.cpp | |||
| @@ -608,7 +608,7 @@ void KScheduler::YieldToAnyThread(KernelCore& kernel) { | |||
| 608 | } | 608 | } |
| 609 | 609 | ||
| 610 | KScheduler::KScheduler(Core::System& system, s32 core_id) : system(system), core_id(core_id) { | 610 | KScheduler::KScheduler(Core::System& system, s32 core_id) : system(system), core_id(core_id) { |
| 611 | switch_fiber = std::make_shared<Common::Fiber>(OnSwitch, this); | 611 | switch_fiber = std::make_unique<Common::Fiber>(OnSwitch, this); |
| 612 | state.needs_scheduling.store(true); | 612 | state.needs_scheduling.store(true); |
| 613 | state.interrupt_task_thread_runnable = false; | 613 | state.interrupt_task_thread_runnable = false; |
| 614 | state.should_count_idle = false; | 614 | state.should_count_idle = false; |
| @@ -726,15 +726,15 @@ void KScheduler::ScheduleImpl() { | |||
| 726 | // Save context for previous thread | 726 | // Save context for previous thread |
| 727 | Unload(previous_thread); | 727 | Unload(previous_thread); |
| 728 | 728 | ||
| 729 | std::shared_ptr<Common::Fiber>* old_context; | 729 | Common::Fiber* old_context; |
| 730 | if (previous_thread != nullptr) { | 730 | if (previous_thread != nullptr) { |
| 731 | old_context = &previous_thread->GetHostContext(); | 731 | old_context = previous_thread->GetHostContext(); |
| 732 | } else { | 732 | } else { |
| 733 | old_context = &idle_thread->GetHostContext(); | 733 | old_context = idle_thread->GetHostContext(); |
| 734 | } | 734 | } |
| 735 | guard.unlock(); | 735 | guard.unlock(); |
| 736 | 736 | ||
| 737 | Common::Fiber::YieldTo(*old_context, switch_fiber); | 737 | Common::Fiber::YieldTo(old_context, switch_fiber.get()); |
| 738 | /// When a thread wakes up, the scheduler may have changed to other in another core. | 738 | /// When a thread wakes up, the scheduler may have changed to other in another core. |
| 739 | auto& next_scheduler = *system.Kernel().CurrentScheduler(); | 739 | auto& next_scheduler = *system.Kernel().CurrentScheduler(); |
| 740 | next_scheduler.SwitchContextStep2(); | 740 | next_scheduler.SwitchContextStep2(); |
| @@ -769,13 +769,13 @@ void KScheduler::SwitchToCurrent() { | |||
| 769 | break; | 769 | break; |
| 770 | } | 770 | } |
| 771 | } | 771 | } |
| 772 | std::shared_ptr<Common::Fiber>* next_context; | 772 | Common::Fiber* next_context; |
| 773 | if (next_thread != nullptr) { | 773 | if (next_thread != nullptr) { |
| 774 | next_context = &next_thread->GetHostContext(); | 774 | next_context = next_thread->GetHostContext(); |
| 775 | } else { | 775 | } else { |
| 776 | next_context = &idle_thread->GetHostContext(); | 776 | next_context = idle_thread->GetHostContext(); |
| 777 | } | 777 | } |
| 778 | Common::Fiber::YieldTo(switch_fiber, *next_context); | 778 | Common::Fiber::YieldTo(switch_fiber.get(), next_context); |
| 779 | } while (!is_switch_pending()); | 779 | } while (!is_switch_pending()); |
| 780 | } | 780 | } |
| 781 | } | 781 | } |
diff --git a/src/core/hle/kernel/k_scheduler.h b/src/core/hle/kernel/k_scheduler.h index f595b9a5c..a4285c595 100644 --- a/src/core/hle/kernel/k_scheduler.h +++ b/src/core/hle/kernel/k_scheduler.h | |||
| @@ -68,12 +68,12 @@ public: | |||
| 68 | 68 | ||
| 69 | void OnThreadStart(); | 69 | void OnThreadStart(); |
| 70 | 70 | ||
| 71 | [[nodiscard]] std::shared_ptr<Common::Fiber>& ControlContext() { | 71 | [[nodiscard]] Common::Fiber* ControlContext() { |
| 72 | return switch_fiber; | 72 | return switch_fiber.get(); |
| 73 | } | 73 | } |
| 74 | 74 | ||
| 75 | [[nodiscard]] const std::shared_ptr<Common::Fiber>& ControlContext() const { | 75 | [[nodiscard]] const Common::Fiber* ControlContext() const { |
| 76 | return switch_fiber; | 76 | return switch_fiber.get(); |
| 77 | } | 77 | } |
| 78 | 78 | ||
| 79 | [[nodiscard]] u64 UpdateHighestPriorityThread(KThread* highest_thread); | 79 | [[nodiscard]] u64 UpdateHighestPriorityThread(KThread* highest_thread); |
| @@ -178,7 +178,7 @@ private: | |||
| 178 | 178 | ||
| 179 | KThread* idle_thread; | 179 | KThread* idle_thread; |
| 180 | 180 | ||
| 181 | std::shared_ptr<Common::Fiber> switch_fiber{}; | 181 | std::unique_ptr<Common::Fiber> switch_fiber{}; |
| 182 | 182 | ||
| 183 | struct SchedulingState { | 183 | struct SchedulingState { |
| 184 | std::atomic<bool> needs_scheduling; | 184 | std::atomic<bool> needs_scheduling; |
diff --git a/src/core/hle/kernel/k_thread.cpp b/src/core/hle/kernel/k_thread.cpp index 1661afbd9..f49e31b72 100644 --- a/src/core/hle/kernel/k_thread.cpp +++ b/src/core/hle/kernel/k_thread.cpp | |||
| @@ -991,10 +991,6 @@ void KThread::SetState(ThreadState state) { | |||
| 991 | } | 991 | } |
| 992 | } | 992 | } |
| 993 | 993 | ||
| 994 | std::shared_ptr<Common::Fiber>& KThread::GetHostContext() { | ||
| 995 | return host_context; | ||
| 996 | } | ||
| 997 | |||
| 998 | ResultVal<std::shared_ptr<KThread>> KThread::Create(Core::System& system, ThreadType type_flags, | 994 | ResultVal<std::shared_ptr<KThread>> KThread::Create(Core::System& system, ThreadType type_flags, |
| 999 | std::string name, VAddr entry_point, | 995 | std::string name, VAddr entry_point, |
| 1000 | u32 priority, u64 arg, s32 processor_id, | 996 | u32 priority, u64 arg, s32 processor_id, |
| @@ -1028,7 +1024,7 @@ ResultVal<std::shared_ptr<KThread>> KThread::Create(Core::System& system, Thread | |||
| 1028 | scheduler.AddThread(thread); | 1024 | scheduler.AddThread(thread); |
| 1029 | 1025 | ||
| 1030 | thread->host_context = | 1026 | thread->host_context = |
| 1031 | std::make_shared<Common::Fiber>(std::move(thread_start_func), thread_start_parameter); | 1027 | std::make_unique<Common::Fiber>(std::move(thread_start_func), thread_start_parameter); |
| 1032 | 1028 | ||
| 1033 | return MakeResult<std::shared_ptr<KThread>>(std::move(thread)); | 1029 | return MakeResult<std::shared_ptr<KThread>>(std::move(thread)); |
| 1034 | } | 1030 | } |
diff --git a/src/core/hle/kernel/k_thread.h b/src/core/hle/kernel/k_thread.h index c8ac656a4..a2893d939 100644 --- a/src/core/hle/kernel/k_thread.h +++ b/src/core/hle/kernel/k_thread.h | |||
| @@ -293,7 +293,13 @@ public: | |||
| 293 | return thread_context_64; | 293 | return thread_context_64; |
| 294 | } | 294 | } |
| 295 | 295 | ||
| 296 | [[nodiscard]] std::shared_ptr<Common::Fiber>& GetHostContext(); | 296 | [[nodiscard]] Common::Fiber* GetHostContext() { |
| 297 | return host_context.get(); | ||
| 298 | } | ||
| 299 | |||
| 300 | [[nodiscard]] const Common::Fiber* GetHostContext() const { | ||
| 301 | return host_context.get(); | ||
| 302 | } | ||
| 297 | 303 | ||
| 298 | [[nodiscard]] ThreadState GetState() const { | 304 | [[nodiscard]] ThreadState GetState() const { |
| 299 | return thread_state & ThreadState::Mask; | 305 | return thread_state & ThreadState::Mask; |
| @@ -719,7 +725,7 @@ private: | |||
| 719 | Common::SpinLock context_guard{}; | 725 | Common::SpinLock context_guard{}; |
| 720 | 726 | ||
| 721 | // For emulation | 727 | // For emulation |
| 722 | std::shared_ptr<Common::Fiber> host_context{}; | 728 | std::unique_ptr<Common::Fiber> host_context{}; |
| 723 | 729 | ||
| 724 | // For debugging | 730 | // For debugging |
| 725 | std::vector<KSynchronizationObject*> wait_objects_for_debugging; | 731 | std::vector<KSynchronizationObject*> wait_objects_for_debugging; |
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index cc8fa6576..d04116115 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp | |||
| @@ -2626,8 +2626,7 @@ void Call(Core::System& system, u32 immediate) { | |||
| 2626 | kernel.ExitSVCProfile(); | 2626 | kernel.ExitSVCProfile(); |
| 2627 | 2627 | ||
| 2628 | if (!thread->IsCallingSvc()) { | 2628 | if (!thread->IsCallingSvc()) { |
| 2629 | auto* host_context = thread->GetHostContext().get(); | 2629 | thread->GetHostContext()->Rewind(); |
| 2630 | host_context->Rewind(); | ||
| 2631 | } | 2630 | } |
| 2632 | 2631 | ||
| 2633 | system.EnterDynarmicProfile(); | 2632 | system.EnterDynarmicProfile(); |
diff --git a/src/tests/common/fibers.cpp b/src/tests/common/fibers.cpp index d94492fc6..b2ded2065 100644 --- a/src/tests/common/fibers.cpp +++ b/src/tests/common/fibers.cpp | |||
| @@ -67,16 +67,15 @@ void TestControl1::DoWork() { | |||
| 67 | value++; | 67 | value++; |
| 68 | } | 68 | } |
| 69 | results[id] = value; | 69 | results[id] = value; |
| 70 | Fiber::YieldTo(work_fibers[id], thread_fibers[id]); | 70 | Fiber::YieldTo(work_fibers[id].get(), thread_fibers[id].get()); |
| 71 | } | 71 | } |
| 72 | 72 | ||
| 73 | void TestControl1::ExecuteThread(u32 id) { | 73 | void TestControl1::ExecuteThread(u32 id) { |
| 74 | thread_ids.Register(id); | 74 | thread_ids.Register(id); |
| 75 | auto thread_fiber = Fiber::ThreadToFiber(); | 75 | thread_fibers[id] = Fiber::ThreadToFiber(); |
| 76 | thread_fibers[id] = thread_fiber; | ||
| 77 | work_fibers[id] = std::make_shared<Fiber>(std::function<void(void*)>{WorkControl1}, this); | 76 | work_fibers[id] = std::make_shared<Fiber>(std::function<void(void*)>{WorkControl1}, this); |
| 78 | items[id] = rand() % 256; | 77 | items[id] = rand() % 256; |
| 79 | Fiber::YieldTo(thread_fibers[id], work_fibers[id]); | 78 | Fiber::YieldTo(thread_fibers[id].get(), work_fibers[id].get()); |
| 80 | thread_fibers[id]->Exit(); | 79 | thread_fibers[id]->Exit(); |
| 81 | } | 80 | } |
| 82 | 81 | ||
| @@ -117,11 +116,11 @@ public: | |||
| 117 | for (u32 i = 0; i < 12000; i++) { | 116 | for (u32 i = 0; i < 12000; i++) { |
| 118 | value1 += i; | 117 | value1 += i; |
| 119 | } | 118 | } |
| 120 | Fiber::YieldTo(fiber1, fiber3); | 119 | Fiber::YieldTo(fiber1.get(), fiber3.get()); |
| 121 | const u32 id = thread_ids.Get(); | 120 | const u32 id = thread_ids.Get(); |
| 122 | assert1 = id == 1; | 121 | assert1 = id == 1; |
| 123 | value2 += 5000; | 122 | value2 += 5000; |
| 124 | Fiber::YieldTo(fiber1, thread_fibers[id]); | 123 | Fiber::YieldTo(fiber1.get(), thread_fibers[id].get()); |
| 125 | } | 124 | } |
| 126 | 125 | ||
| 127 | void DoWork2() { | 126 | void DoWork2() { |
| @@ -129,7 +128,7 @@ public: | |||
| 129 | ; | 128 | ; |
| 130 | value2 = 2000; | 129 | value2 = 2000; |
| 131 | trap = false; | 130 | trap = false; |
| 132 | Fiber::YieldTo(fiber2, fiber1); | 131 | Fiber::YieldTo(fiber2.get(), fiber1.get()); |
| 133 | assert3 = false; | 132 | assert3 = false; |
| 134 | } | 133 | } |
| 135 | 134 | ||
| @@ -137,19 +136,19 @@ public: | |||
| 137 | const u32 id = thread_ids.Get(); | 136 | const u32 id = thread_ids.Get(); |
| 138 | assert2 = id == 0; | 137 | assert2 = id == 0; |
| 139 | value1 += 1000; | 138 | value1 += 1000; |
| 140 | Fiber::YieldTo(fiber3, thread_fibers[id]); | 139 | Fiber::YieldTo(fiber3.get(), thread_fibers[id].get()); |
| 141 | } | 140 | } |
| 142 | 141 | ||
| 143 | void ExecuteThread(u32 id); | 142 | void ExecuteThread(u32 id); |
| 144 | 143 | ||
| 145 | void CallFiber1() { | 144 | void CallFiber1() { |
| 146 | const u32 id = thread_ids.Get(); | 145 | const u32 id = thread_ids.Get(); |
| 147 | Fiber::YieldTo(thread_fibers[id], fiber1); | 146 | Fiber::YieldTo(thread_fibers[id].get(), fiber1.get()); |
| 148 | } | 147 | } |
| 149 | 148 | ||
| 150 | void CallFiber2() { | 149 | void CallFiber2() { |
| 151 | const u32 id = thread_ids.Get(); | 150 | const u32 id = thread_ids.Get(); |
| 152 | Fiber::YieldTo(thread_fibers[id], fiber2); | 151 | Fiber::YieldTo(thread_fibers[id].get(), fiber2.get()); |
| 153 | } | 152 | } |
| 154 | 153 | ||
| 155 | void Exit(); | 154 | void Exit(); |
| @@ -185,8 +184,7 @@ static void WorkControl2_3(void* control) { | |||
| 185 | 184 | ||
| 186 | void TestControl2::ExecuteThread(u32 id) { | 185 | void TestControl2::ExecuteThread(u32 id) { |
| 187 | thread_ids.Register(id); | 186 | thread_ids.Register(id); |
| 188 | auto thread_fiber = Fiber::ThreadToFiber(); | 187 | thread_fibers[id] = Fiber::ThreadToFiber(); |
| 189 | thread_fibers[id] = thread_fiber; | ||
| 190 | } | 188 | } |
| 191 | 189 | ||
| 192 | void TestControl2::Exit() { | 190 | void TestControl2::Exit() { |
| @@ -241,23 +239,23 @@ public: | |||
| 241 | 239 | ||
| 242 | void DoWork1() { | 240 | void DoWork1() { |
| 243 | value1 += 1; | 241 | value1 += 1; |
| 244 | Fiber::YieldTo(fiber1, fiber2); | 242 | Fiber::YieldTo(fiber1.get(), fiber2.get()); |
| 245 | const u32 id = thread_ids.Get(); | 243 | const u32 id = thread_ids.Get(); |
| 246 | value3 += 1; | 244 | value3 += 1; |
| 247 | Fiber::YieldTo(fiber1, thread_fibers[id]); | 245 | Fiber::YieldTo(fiber1.get(), thread_fibers[id].get()); |
| 248 | } | 246 | } |
| 249 | 247 | ||
| 250 | void DoWork2() { | 248 | void DoWork2() { |
| 251 | value2 += 1; | 249 | value2 += 1; |
| 252 | const u32 id = thread_ids.Get(); | 250 | const u32 id = thread_ids.Get(); |
| 253 | Fiber::YieldTo(fiber2, thread_fibers[id]); | 251 | Fiber::YieldTo(fiber2.get(), thread_fibers[id].get()); |
| 254 | } | 252 | } |
| 255 | 253 | ||
| 256 | void ExecuteThread(u32 id); | 254 | void ExecuteThread(u32 id); |
| 257 | 255 | ||
| 258 | void CallFiber1() { | 256 | void CallFiber1() { |
| 259 | const u32 id = thread_ids.Get(); | 257 | const u32 id = thread_ids.Get(); |
| 260 | Fiber::YieldTo(thread_fibers[id], fiber1); | 258 | Fiber::YieldTo(thread_fibers[id].get(), fiber1.get()); |
| 261 | } | 259 | } |
| 262 | 260 | ||
| 263 | void Exit(); | 261 | void Exit(); |
| @@ -266,7 +264,7 @@ public: | |||
| 266 | u32 value2{}; | 264 | u32 value2{}; |
| 267 | u32 value3{}; | 265 | u32 value3{}; |
| 268 | ThreadIds thread_ids; | 266 | ThreadIds thread_ids; |
| 269 | std::vector<std::shared_ptr<Common::Fiber>> thread_fibers; | 267 | std::vector<std::unique_ptr<Common::Fiber>> thread_fibers; |
| 270 | std::shared_ptr<Common::Fiber> fiber1; | 268 | std::shared_ptr<Common::Fiber> fiber1; |
| 271 | std::shared_ptr<Common::Fiber> fiber2; | 269 | std::shared_ptr<Common::Fiber> fiber2; |
| 272 | }; | 270 | }; |
| @@ -283,8 +281,7 @@ static void WorkControl3_2(void* control) { | |||
| 283 | 281 | ||
| 284 | void TestControl3::ExecuteThread(u32 id) { | 282 | void TestControl3::ExecuteThread(u32 id) { |
| 285 | thread_ids.Register(id); | 283 | thread_ids.Register(id); |
| 286 | auto thread_fiber = Fiber::ThreadToFiber(); | 284 | thread_fibers[id] = Fiber::ThreadToFiber(); |
| 287 | thread_fibers[id] = thread_fiber; | ||
| 288 | } | 285 | } |
| 289 | 286 | ||
| 290 | void TestControl3::Exit() { | 287 | void TestControl3::Exit() { |
| @@ -332,7 +329,7 @@ public: | |||
| 332 | 329 | ||
| 333 | void Execute() { | 330 | void Execute() { |
| 334 | thread_fiber = Fiber::ThreadToFiber(); | 331 | thread_fiber = Fiber::ThreadToFiber(); |
| 335 | Fiber::YieldTo(thread_fiber, fiber1); | 332 | Fiber::YieldTo(thread_fiber.get(), fiber1.get()); |
| 336 | thread_fiber->Exit(); | 333 | thread_fiber->Exit(); |
| 337 | } | 334 | } |
| 338 | 335 | ||
| @@ -340,7 +337,7 @@ public: | |||
| 340 | fiber1->SetRewindPoint(std::function<void(void*)>{WorkControl4}, this); | 337 | fiber1->SetRewindPoint(std::function<void(void*)>{WorkControl4}, this); |
| 341 | if (rewinded) { | 338 | if (rewinded) { |
| 342 | goal_reached = true; | 339 | goal_reached = true; |
| 343 | Fiber::YieldTo(fiber1, thread_fiber); | 340 | Fiber::YieldTo(fiber1.get(), thread_fiber.get()); |
| 344 | } | 341 | } |
| 345 | rewinded = true; | 342 | rewinded = true; |
| 346 | fiber1->Rewind(); | 343 | fiber1->Rewind(); |