Просмотр исходного кода

common: ThreadWorker: Add class to help do asynchronous work.

bunnei 5 лет назад
Родитель
Сommit
69e82d01d5
3 измененных файлов с 90 добавлено и 0 удалено
  1. 2 0
      src/common/CMakeLists.txt
  2. 58 0
      src/common/thread_worker.cpp
  3. 30 0
      src/common/thread_worker.h

+ 2 - 0
src/common/CMakeLists.txt

@@ -162,6 +162,8 @@ add_library(common STATIC
     thread.cpp
     thread.cpp
     thread.h
     thread.h
     thread_queue_list.h
     thread_queue_list.h
+    thread_worker.cpp
+    thread_worker.h
     threadsafe_queue.h
     threadsafe_queue.h
     time_zone.cpp
     time_zone.cpp
     time_zone.h
     time_zone.h

+ 58 - 0
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

+ 30 - 0
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