Foundation
Loading...
Searching...
No Matches
ThreadPool.hpp
Go to the documentation of this file.
1#pragma once
2#include <Atomics/Queue.hpp>
3#include <Bits/Ranges.hpp>
4#include <Core/Core.hpp>
5#include "Future.hpp"
6#include "Thread.hpp"
7namespace Foundation::Async
8{
9 using namespace Core;
10 using namespace Async;
11 using namespace Atomics;
19 {
20 virtual ~ThreadPoolJob() = default;
21 virtual void Execute(size_t id) noexcept = 0;
22 };
31 template <typename Lambda, typename ReturnType>
33 {
36 public:
38 void Execute(size_t) noexcept override
39 {
40 try
41 {
42 if constexpr (std::is_same_v<ReturnType, void>)
43 {
44 mFunc();
45 mPromise->set_value();
46 }
47 else
48 mPromise->set_value(mFunc());
49 }
50 catch (...)
51 {
52 mPromise->set_exception(std::current_exception());
53 }
54 }
55 };
64 {
70
72 JobQueue::Writer mJobsWriter;
73 // Ensure threads are joined first on destruction
75 void ThreadPoolWorker(size_t id);
76 public:
84 ThreadPool(size_t numThreads, size_t maxTasks, Allocator* alloc, StringView name = "ThreadPool");
91 template <typename T, typename ... Args>
92 requires std::is_base_of_v<ThreadPoolJob, T>
93 void PushImpl(Args&&... args)
94 {
95 CHECK_MSG(!mShutdown, "ThreadPool shutting down");
97 ConstructUniqueBase<ThreadPoolJob, T>(mAllocator, std::forward<Args>(args)...)), "Jobs full");
98 mTotal.fetch_add(1, std::memory_order_relaxed);
99 mTotal.notify_one();
100 }
105 template <typename Lambda, typename... Args>
106 auto Push(Lambda&& func, Args&&... args)
107 {
108 CHECK_MSG(!mShutdown, "ThreadPool shutting down");
109 auto ThreadPoolPackagedLambda = [](Lambda&& fn, Args&&... fargs)
110 {
111 return [func = std::forward<Lambda>(fn), ... fargs = std::forward<Args>(fargs)]
112 { return func(std::forward<Args>(fargs)...); };
113 };
114 auto packaged = ThreadPoolPackagedLambda(std::forward<Lambda>(func), std::forward<Args>(args)...);
115 using ReturnType = decltype(func(args...));
116 using PackagedType = decltype(packaged);
117 // Use the wrapped lambda type for the job
123 std::forward<PackagedType>(packaged))), "Jobs full");
124 mTotal.fetch_add(1, std::memory_order_relaxed);
125 mTotal.notify_one();
126 return promise;
127 }
132 void Shutdown();
137 void Join();
141 ~ThreadPool();
142 };
143} // namespace Foundation::Async
#define CHECK_MSG(expr, format_str,...)
Definition Logging.hpp:31
State-carrying lambda job for use with ThreadPool.
Definition ThreadPool.hpp:33
SharedPromise< ReturnType > mPromise
Definition ThreadPool.hpp:35
void Execute(size_t) noexcept override
Definition ThreadPool.hpp:38
ThreadPoolLambdaJob(SharedPromise< ReturnType > promise, Lambda &&func)
Definition ThreadPool.hpp:37
Lambda mFunc
Definition ThreadPool.hpp:34
Atomic, lock-free Thread Pool implementation with fixed bounds.
Definition ThreadPool.hpp:64
auto Push(Lambda &&func, Args &&... args)
Push a lambda job to the thread pool.
Definition ThreadPool.hpp:106
Allocator * mAllocator
Definition ThreadPool.hpp:65
void Join()
Wait for all scheduled jobs to complete.
Definition ThreadPool.cpp:18
JobQueue mJobs
Definition ThreadPool.hpp:71
~ThreadPool()
Definition ThreadPool.cpp:27
void PushImpl(Args &&... args)
Push a job implementing ThreadPoolJob to the thread pool.
Definition ThreadPool.hpp:93
JobQueue::Writer mJobsWriter
Definition ThreadPool.hpp:72
Vector< Thread > mThreads
Definition ThreadPool.hpp:74
Atomic< size_t > mComplete
Definition ThreadPool.hpp:68
Atomic< bool > mShutdown
Definition ThreadPool.hpp:67
Atomic< size_t > mTotal
Definition ThreadPool.hpp:69
void Shutdown()
Shutdown the ThreadPool, potentially cancelling all pending jobs.
Definition ThreadPool.cpp:12
String mName
Definition ThreadPool.hpp:66
void ThreadPoolWorker(size_t id)
Definition ThreadPool.cpp:31
General Purpose Allocator (GPA) interface.
Definition Allocator.hpp:24
Asynchronous programming primitives.
Definition Future.hpp:8
std::basic_string< char > String
Alias for std::basic_string<char>, without an explicit allocator constructor.
Definition Container.hpp:141
std::basic_string_view< char > StringView
Alias for std::basic_string_view<char>
Definition Container.hpp:53
std::unique_ptr< T, StlDeleter< T > > UniquePtr
std::unique_ptr with custom deleter that uses a Foundation::Core::Allocator to deallocate memory.
Definition Allocator.hpp:161
Job interface for use with ThreadPool.
Definition ThreadPool.hpp:19
virtual ~ThreadPoolJob()=default
virtual void Execute(size_t id) noexcept=0