aboutsummaryrefslogtreecommitdiff
path: root/zencore
diff options
context:
space:
mode:
authorDan Engelbrecht <[email protected]>2022-03-22 13:50:08 +0100
committerGitHub <[email protected]>2022-03-22 13:50:08 +0100
commit8667509907b8829b5148ee856dce675001051b01 (patch)
tree0252caa7cd01c533809b1b17dfa41721a0cccb82 /zencore
parentRemove unused TotalAttachmentsSize (Mac warning) (diff)
downloadzen-8667509907b8829b5148ee856dce675001051b01.tar.xz
zen-8667509907b8829b5148ee856dce675001051b01.zip
move workthreadpool to zencore (#63)
Diffstat (limited to 'zencore')
-rw-r--r--zencore/include/zencore/workthreadpool.h46
-rw-r--r--zencore/workthreadpool.cpp77
2 files changed, 123 insertions, 0 deletions
diff --git a/zencore/include/zencore/workthreadpool.h b/zencore/include/zencore/workthreadpool.h
new file mode 100644
index 000000000..834339d50
--- /dev/null
+++ b/zencore/include/zencore/workthreadpool.h
@@ -0,0 +1,46 @@
+// Copyright Epic Games, Inc. All Rights Reserved.
+
+#pragma once
+
+#include <zencore/zencore.h>
+
+#include <zencore/blockingqueue.h>
+#include <zencore/refcount.h>
+
+#include <exception>
+#include <functional>
+#include <system_error>
+#include <thread>
+#include <vector>
+
+namespace zen {
+
+struct IWork : public RefCounted
+{
+ virtual void Execute() = 0;
+
+ inline std::exception_ptr GetException() { return m_Exception; }
+
+private:
+ std::exception_ptr m_Exception;
+
+ friend class WorkerThreadPool;
+};
+
+class WorkerThreadPool
+{
+public:
+ WorkerThreadPool(int InThreadCount);
+ ~WorkerThreadPool();
+
+ void ScheduleWork(Ref<IWork> Work);
+ void ScheduleWork(std::function<void()>&& Work);
+
+ void WorkerThreadFunction();
+
+private:
+ std::vector<std::thread> m_WorkerThreads;
+ BlockingQueue<Ref<IWork>> m_WorkQueue;
+};
+
+} // namespace zen
diff --git a/zencore/workthreadpool.cpp b/zencore/workthreadpool.cpp
new file mode 100644
index 000000000..3fd1d11a6
--- /dev/null
+++ b/zencore/workthreadpool.cpp
@@ -0,0 +1,77 @@
+// Copyright Epic Games, Inc. All Rights Reserved.
+
+#include <zencore/workthreadpool.h>
+
+#include <zencore/logging.h>
+
+namespace zen {
+
+namespace detail {
+ struct LambdaWork : IWork
+ {
+ LambdaWork(auto Work) : WorkFunction(Work) {}
+ virtual void Execute() override { WorkFunction(); }
+
+ std::function<void()> WorkFunction;
+ };
+} // namespace detail
+
+WorkerThreadPool::WorkerThreadPool(int InThreadCount)
+{
+ for (int i = 0; i < InThreadCount; ++i)
+ {
+ m_WorkerThreads.emplace_back(&WorkerThreadPool::WorkerThreadFunction, this);
+ }
+}
+
+WorkerThreadPool::~WorkerThreadPool()
+{
+ m_WorkQueue.CompleteAdding();
+
+ for (std::thread& Thread : m_WorkerThreads)
+ {
+ Thread.join();
+ }
+
+ m_WorkerThreads.clear();
+}
+
+void
+WorkerThreadPool::ScheduleWork(Ref<IWork> Work)
+{
+ m_WorkQueue.Enqueue(std::move(Work));
+}
+
+void
+WorkerThreadPool::ScheduleWork(std::function<void()>&& Work)
+{
+ m_WorkQueue.Enqueue(new detail::LambdaWork(Work));
+}
+
+void
+WorkerThreadPool::WorkerThreadFunction()
+{
+ do
+ {
+ Ref<IWork> Work;
+ if (m_WorkQueue.WaitAndDequeue(Work))
+ {
+ try
+ {
+ Work->Execute();
+ }
+ catch (std::exception& e)
+ {
+ Work->m_Exception = std::current_exception();
+
+ ZEN_WARN("Caught exception in worker thread: {}", e.what());
+ }
+ }
+ else
+ {
+ return;
+ }
+ } while (true);
+}
+
+} // namespace zen \ No newline at end of file