diff options
| author | Jordan Woyak <jordan.woyak@gmail.com> | 2025-11-17 02:51:26 -0600 |
|---|---|---|
| committer | Jordan Woyak <jordan.woyak@gmail.com> | 2025-11-18 14:19:21 -0600 |
| commit | d25742fe8bb475b6bdf03e80cc09350e9c3d3b5a (patch) | |
| tree | 7fe34239450c159f7de8140c19e3821dde104127 | |
| parent | 605cc579a436d6028cc5cbe4a3f720d0ad35e24f (diff) | |
Common: Introduce a OneShotEvent class. Unlike Common::Event, OneShotEvent is safe in situations when being immediately destructed.
| -rw-r--r-- | Source/Core/Common/CMakeLists.txt | 1 | ||||
| -rw-r--r-- | Source/Core/Common/OneShotEvent.h | 55 | ||||
| -rw-r--r-- | Source/Core/DolphinLib.props | 1 |
3 files changed, 57 insertions, 0 deletions
diff --git a/Source/Core/Common/CMakeLists.txt b/Source/Core/Common/CMakeLists.txt index e833893a9d..2447d1ed40 100644 --- a/Source/Core/Common/CMakeLists.txt +++ b/Source/Core/Common/CMakeLists.txt @@ -118,6 +118,7 @@ add_library(common NandPaths.h Network.cpp Network.h + OneShotEvent.h PcapFile.cpp PcapFile.h Profiler.cpp diff --git a/Source/Core/Common/OneShotEvent.h b/Source/Core/Common/OneShotEvent.h new file mode 100644 index 0000000000..312848ed91 --- /dev/null +++ b/Source/Core/Common/OneShotEvent.h @@ -0,0 +1,55 @@ +// Copyright 2025 Dolphin Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include <chrono> +#include <memory> +#include <semaphore> + +#include "Common/Functional.h" + +namespace Common +{ + +// A one-time-use single-producer single-consumer thread synchronization class. +// Safe when `Set` will cause a `Wait`ing thread to immediately destruct the event itself. +class OneShotEvent +{ +public: + // One thread should call Set() exactly once. + void Set() { m_semaphore.release(1); } + + // One thread may call Wait() once or WaitFor() until it returns true. + + void Wait() { m_semaphore.acquire(); } + + template <typename Rep, typename Period> + bool WaitFor(const std::chrono::duration<Rep, Period>& rel_time) + { + return m_semaphore.try_acquire_for(rel_time); + } + +private: + std::binary_semaphore m_semaphore{0}; +}; + +// Invokes Set() on the given object upon destruction. +template <typename EventType> +class ScopedSetter +{ +public: + ScopedSetter() = default; + explicit ScopedSetter(EventType* ptr) : m_ptr{ptr} {} + + // Forgets the object without invoking Set(). + void Dismiss() { m_ptr.release(); } + +private: + // Leveraging unique_ptr conveniently makes this class move-only. + // It does no actual deletion, just calls Set(). + using NonOwningSetOnDeletePtr = std::unique_ptr<EventType, InvokerOf<&EventType::Set>>; + NonOwningSetOnDeletePtr m_ptr; +}; + +} // namespace Common diff --git a/Source/Core/DolphinLib.props b/Source/Core/DolphinLib.props index 3cfac5838c..f4a9c04a92 100644 --- a/Source/Core/DolphinLib.props +++ b/Source/Core/DolphinLib.props @@ -149,6 +149,7 @@ <ClInclude Include="Common\Mutex.h" /> <ClInclude Include="Common\NandPaths.h" /> <ClInclude Include="Common\Network.h" /> + <ClInclude Include="Common\OneShotEvent.h" /> <ClInclude Include="Common\PcapFile.h" /> <ClInclude Include="Common\Profiler.h" /> <ClInclude Include="Common\Projection.h" /> |
