summaryrefslogtreecommitdiff
path: root/Source/Core/Common/WorkQueueThread.h
diff options
context:
space:
mode:
authorMichael M <mchtly@gmail.com>2017-08-20 14:04:49 -0700
committerMichael M <mchtly@gmail.com>2017-08-20 14:40:56 -0700
commitde9378bf6389ad22ca955df477a48bd678c10c9e (patch)
treec12f370737390b9d8159ecab2fe38739ee90e62d /Source/Core/Common/WorkQueueThread.h
parent16d6ccbdf7bed6a1da122e0bcd0747d9bcbd650f (diff)
Common: add WorkQueueThread
Diffstat (limited to 'Source/Core/Common/WorkQueueThread.h')
-rw-r--r--Source/Core/Common/WorkQueueThread.h86
1 files changed, 86 insertions, 0 deletions
diff --git a/Source/Core/Common/WorkQueueThread.h b/Source/Core/Common/WorkQueueThread.h
new file mode 100644
index 0000000000..8947b099cb
--- /dev/null
+++ b/Source/Core/Common/WorkQueueThread.h
@@ -0,0 +1,86 @@
+// Copyright 2017 Dolphin Emulator Project
+// Licensed under GPLv2+
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include <functional>
+#include <queue>
+#include <thread>
+
+#include "Common/Event.h"
+#include "Common/Flag.h"
+
+// A thread that executes the given function for every item placed into its queue.
+
+namespace Common
+{
+template <typename T>
+class WorkQueueThread
+{
+public:
+ WorkQueueThread() = default;
+ WorkQueueThread(std::function<void(T)> function) { Reset(std::move(function)); }
+ ~WorkQueueThread() { Shutdown(); }
+ void Reset(std::function<void(T)> function)
+ {
+ Shutdown();
+ m_shutdown.Clear();
+ m_function = std::move(function);
+ m_thread = std::thread([this] { ThreadLoop(); });
+ }
+
+ template <typename... Args>
+ void EmplaceItem(Args&&... args)
+ {
+ {
+ std::unique_lock<std::mutex> lg(m_lock);
+ m_items.emplace(std::move(args)...);
+ }
+ m_wakeup.Set();
+ }
+
+private:
+ void Shutdown()
+ {
+ if (m_thread.joinable())
+ {
+ m_shutdown.Set();
+ m_wakeup.Set();
+ m_thread.join();
+ }
+ }
+
+ void ThreadLoop()
+ {
+ while (true)
+ {
+ m_wakeup.Wait();
+
+ while (true)
+ {
+ T item;
+ {
+ std::unique_lock<std::mutex> lg(m_lock);
+ if (m_items.empty())
+ break;
+ item = m_items.front();
+ m_items.pop();
+ }
+ m_function(std::move(item));
+ }
+
+ if (m_shutdown.IsSet())
+ break;
+ }
+ }
+
+ std::function<void(T)> m_function;
+ std::thread m_thread;
+ Common::Event m_wakeup;
+ Common::Flag m_shutdown;
+ std::mutex m_lock;
+ std::queue<T> m_items;
+};
+
+} // namespace Common