diff options
| author | bunnei <bunneidev@gmail.com> | 2020-12-29 16:36:35 -0800 | 
|---|---|---|
| committer | bunnei <bunneidev@gmail.com> | 2020-12-29 16:46:29 -0800 | 
| commit | 69e82d01d5012c0078f65a294ecbb7118707f73c (patch) | |
| tree | d8bac45fa91904abec67a0d76c29e4f7e3aeaab8 | |
| parent | c192da3f82ea3b2563ce43a340c88ac9a6602f26 (diff) | |
common: ThreadWorker: Add class to help do asynchronous work.
| -rw-r--r-- | src/common/CMakeLists.txt | 2 | ||||
| -rw-r--r-- | src/common/thread_worker.cpp | 58 | ||||
| -rw-r--r-- | src/common/thread_worker.h | 30 | 
3 files changed, 90 insertions, 0 deletions
| diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index 943ff996e..5c8003eb1 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt @@ -162,6 +162,8 @@ add_library(common STATIC      thread.cpp      thread.h      thread_queue_list.h +    thread_worker.cpp +    thread_worker.h      threadsafe_queue.h      time_zone.cpp      time_zone.h diff --git a/src/common/thread_worker.cpp b/src/common/thread_worker.cpp new file mode 100644 index 000000000..8f9bf447a --- /dev/null +++ b/src/common/thread_worker.cpp @@ -0,0 +1,58 @@ +// Copyright 2020 yuzu emulator team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include "common/thread.h" +#include "common/thread_worker.h" + +namespace Common { + +ThreadWorker::ThreadWorker(std::size_t num_workers, const std::string& name) { +    for (std::size_t i = 0; i < num_workers; ++i) +        threads.emplace_back([this, thread_name{std::string{name}}] { +            Common::SetCurrentThreadName(thread_name.c_str()); + +            // Wait for first request +            { +                std::unique_lock lock{queue_mutex}; +                condition.wait(lock, [this] { return stop || !requests.empty(); }); +            } + +            while (true) { +                std::function<void()> task; + +                { +                    std::unique_lock lock{queue_mutex}; +                    condition.wait(lock, [this] { return stop || !requests.empty(); }); +                    if (stop || requests.empty()) { +                        return; +                    } +                    task = std::move(requests.front()); +                    requests.pop(); +                } + +                task(); +            } +        }); +} + +ThreadWorker::~ThreadWorker() { +    { +        std::unique_lock lock{queue_mutex}; +        stop = true; +    } +    condition.notify_all(); +    for (std::thread& thread : threads) { +        thread.join(); +    } +} + +void ThreadWorker::QueueWork(std::function<void()>&& work) { +    { +        std::unique_lock lock{queue_mutex}; +        requests.emplace(work); +    } +    condition.notify_one(); +} + +} // namespace Common diff --git a/src/common/thread_worker.h b/src/common/thread_worker.h new file mode 100644 index 000000000..f1859971f --- /dev/null +++ b/src/common/thread_worker.h @@ -0,0 +1,30 @@ +// Copyright 2020 yuzu emulator team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include <atomic> +#include <functional> +#include <mutex> +#include <string> +#include <vector> +#include <queue> + +namespace Common { + +class ThreadWorker final { +public: +    explicit ThreadWorker(std::size_t num_workers, const std::string& name); +    ~ThreadWorker(); +    void QueueWork(std::function<void()>&& work); + +private: +    std::vector<std::thread> threads; +    std::queue<std::function<void()>> requests; +    std::mutex queue_mutex; +    std::condition_variable condition; +    std::atomic_bool stop{}; +}; + +} // namespace Common | 
