diff --git a/PowerToys.sln b/PowerToys.sln index cd73322e24..eb70eaf85f 100644 --- a/PowerToys.sln +++ b/PowerToys.sln @@ -278,6 +278,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "utils", "utils", "{B39DC643 src\common\utils\modulesRegistry.h = src\common\utils\modulesRegistry.h src\common\utils\MsiUtils.h = src\common\utils\MsiUtils.h src\common\utils\MsWindowsSettings.h = src\common\utils\MsWindowsSettings.h + src\common\utils\OnThreadExecutor.h = src\common\utils\OnThreadExecutor.h src\common\utils\os-detect.h = src\common\utils\os-detect.h src\common\utils\package.h = src\common\utils\package.h src\common\utils\ProcessWaiter.h = src\common\utils\ProcessWaiter.h diff --git a/src/common/utils/OnThreadExecutor.h b/src/common/utils/OnThreadExecutor.h new file mode 100644 index 0000000000..c361a33700 --- /dev/null +++ b/src/common/utils/OnThreadExecutor.h @@ -0,0 +1,72 @@ +#pragma once + +#include +#include +#include +#include +#include + +// OnThreadExecutor allows its caller to off-load some work to a persistently running background thread. +// This might come in handy if you use the API which sets thread-wide global state and the state needs +// to be isolated. + +class OnThreadExecutor final +{ +public: + using task_t = std::packaged_task; + + OnThreadExecutor() : + _shutdown_request{ false }, + _worker_thread{ [this] { worker_thread(); } } + { + } + + ~OnThreadExecutor() + { + _shutdown_request = true; + _task_cv.notify_one(); + _worker_thread.join(); + } + + std::future submit(task_t task) + { + auto future = task.get_future(); + std::lock_guard lock{ _task_mutex }; + _task_queue.emplace(std::move(task)); + _task_cv.notify_one(); + return future; + } + + void cancel() + { + std::lock_guard lock{ _task_mutex }; + _task_queue = {}; + _task_cv.notify_one(); + } + +private: + void worker_thread() + { + while (!_shutdown_request) + { + task_t task; + { + std::unique_lock task_lock{ _task_mutex }; + _task_cv.wait(task_lock, [this] { return !_task_queue.empty() || _shutdown_request; }); + if (_shutdown_request) + { + return; + } + task = std::move(_task_queue.front()); + _task_queue.pop(); + } + task(); + } + } + + std::mutex _task_mutex; + std::condition_variable _task_cv; + std::atomic_bool _shutdown_request; + std::queue> _task_queue; + std::thread _worker_thread; +}; diff --git a/src/modules/Projects/ProjectsSnapshotTool/OnThreadExecutor.cpp b/src/modules/Projects/ProjectsSnapshotTool/OnThreadExecutor.cpp deleted file mode 100644 index 13b7387ed5..0000000000 --- a/src/modules/Projects/ProjectsSnapshotTool/OnThreadExecutor.cpp +++ /dev/null @@ -1,51 +0,0 @@ -#include "pch.h" - -#include "OnThreadExecutor.h" - -OnThreadExecutor::OnThreadExecutor() : - _shutdown_request{ false }, _worker_thread{ [this] { worker_thread(); } } -{ -} - -std::future OnThreadExecutor::submit(task_t task) -{ - auto future = task.get_future(); - std::lock_guard lock{ _task_mutex }; - _task_queue.emplace(std::move(task)); - _task_cv.notify_one(); - return future; -} - -void OnThreadExecutor::cancel() -{ - std::lock_guard lock{ _task_mutex }; - _task_queue = {}; - _task_cv.notify_one(); -} - - -void OnThreadExecutor::worker_thread() -{ - while (!_shutdown_request) - { - task_t task; - { - std::unique_lock task_lock{ _task_mutex }; - _task_cv.wait(task_lock, [this] { return !_task_queue.empty() || _shutdown_request; }); - if (_shutdown_request) - { - return; - } - task = std::move(_task_queue.front()); - _task_queue.pop(); - } - task(); - } -} - -OnThreadExecutor::~OnThreadExecutor() -{ - _shutdown_request = true; - _task_cv.notify_one(); - _worker_thread.join(); -} diff --git a/src/modules/Projects/ProjectsSnapshotTool/OnThreadExecutor.h b/src/modules/Projects/ProjectsSnapshotTool/OnThreadExecutor.h deleted file mode 100644 index 3111602f0f..0000000000 --- a/src/modules/Projects/ProjectsSnapshotTool/OnThreadExecutor.h +++ /dev/null @@ -1,31 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include - -// OnThreadExecutor allows its caller to off-load some work to a persistently running background thread. -// This might come in handy if you use the API which sets thread-wide global state and the state needs -// to be isolated. - -class OnThreadExecutor final -{ -public: - using task_t = std::packaged_task; - - OnThreadExecutor(); - ~OnThreadExecutor(); - std::future submit(task_t task); - void cancel(); - -private: - void worker_thread(); - - std::mutex _task_mutex; - std::condition_variable _task_cv; - std::atomic_bool _shutdown_request; - std::queue> _task_queue; - std::thread _worker_thread; -}; diff --git a/src/modules/Projects/ProjectsSnapshotTool/ProjectsSnapshotTool.vcxproj b/src/modules/Projects/ProjectsSnapshotTool/ProjectsSnapshotTool.vcxproj index 7c42c829df..03074170de 100644 --- a/src/modules/Projects/ProjectsSnapshotTool/ProjectsSnapshotTool.vcxproj +++ b/src/modules/Projects/ProjectsSnapshotTool/ProjectsSnapshotTool.vcxproj @@ -124,7 +124,6 @@ - Create @@ -132,7 +131,6 @@ - diff --git a/src/modules/Projects/ProjectsSnapshotTool/ProjectsSnapshotTool.vcxproj.filters b/src/modules/Projects/ProjectsSnapshotTool/ProjectsSnapshotTool.vcxproj.filters index 8f8b7d9f26..d182bcfb57 100644 --- a/src/modules/Projects/ProjectsSnapshotTool/ProjectsSnapshotTool.vcxproj.filters +++ b/src/modules/Projects/ProjectsSnapshotTool/ProjectsSnapshotTool.vcxproj.filters @@ -21,9 +21,6 @@ Header Files - - Header Files - Header Files @@ -38,9 +35,6 @@ Source Files - - Source Files -