Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/thirdparty/jolt_physics/Jolt/Core/JobSystemThreadPool.h
9906 views
1
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
2
// SPDX-FileCopyrightText: 2021 Jorrit Rouwe
3
// SPDX-License-Identifier: MIT
4
5
#pragma once
6
7
#include <Jolt/Core/JobSystemWithBarrier.h>
8
#include <Jolt/Core/FixedSizeFreeList.h>
9
#include <Jolt/Core/Semaphore.h>
10
11
JPH_SUPPRESS_WARNINGS_STD_BEGIN
12
#include <thread>
13
JPH_SUPPRESS_WARNINGS_STD_END
14
15
JPH_NAMESPACE_BEGIN
16
17
// Things we're using from STL
18
using std::thread;
19
20
/// Implementation of a JobSystem using a thread pool
21
///
22
/// Note that this is considered an example implementation. It is expected that when you integrate
23
/// the physics engine into your own project that you'll provide your own implementation of the
24
/// JobSystem built on top of whatever job system your project uses.
25
class JPH_EXPORT JobSystemThreadPool final : public JobSystemWithBarrier
26
{
27
public:
28
JPH_OVERRIDE_NEW_DELETE
29
30
/// Creates a thread pool.
31
/// @see JobSystemThreadPool::Init
32
JobSystemThreadPool(uint inMaxJobs, uint inMaxBarriers, int inNumThreads = -1);
33
JobSystemThreadPool() = default;
34
virtual ~JobSystemThreadPool() override;
35
36
/// Functions to call when a thread is initialized or exits, must be set before calling Init()
37
using InitExitFunction = function<void(int)>;
38
void SetThreadInitFunction(const InitExitFunction &inInitFunction) { mThreadInitFunction = inInitFunction; }
39
void SetThreadExitFunction(const InitExitFunction &inExitFunction) { mThreadExitFunction = inExitFunction; }
40
41
/// Initialize the thread pool
42
/// @param inMaxJobs Max number of jobs that can be allocated at any time
43
/// @param inMaxBarriers Max number of barriers that can be allocated at any time
44
/// @param inNumThreads Number of threads to start (the number of concurrent jobs is 1 more because the main thread will also run jobs while waiting for a barrier to complete). Use -1 to auto detect the amount of CPU's.
45
void Init(uint inMaxJobs, uint inMaxBarriers, int inNumThreads = -1);
46
47
// See JobSystem
48
virtual int GetMaxConcurrency() const override { return int(mThreads.size()) + 1; }
49
virtual JobHandle CreateJob(const char *inName, ColorArg inColor, const JobFunction &inJobFunction, uint32 inNumDependencies = 0) override;
50
51
/// Change the max concurrency after initialization
52
void SetNumThreads(int inNumThreads) { StopThreads(); StartThreads(inNumThreads); }
53
54
protected:
55
// See JobSystem
56
virtual void QueueJob(Job *inJob) override;
57
virtual void QueueJobs(Job **inJobs, uint inNumJobs) override;
58
virtual void FreeJob(Job *inJob) override;
59
60
private:
61
/// Start/stop the worker threads
62
void StartThreads(int inNumThreads);
63
void StopThreads();
64
65
/// Entry point for a thread
66
void ThreadMain(int inThreadIndex);
67
68
/// Get the head of the thread that has processed the least amount of jobs
69
inline uint GetHead() const;
70
71
/// Internal helper function to queue a job
72
inline void QueueJobInternal(Job *inJob);
73
74
/// Functions to call when initializing or exiting a thread
75
InitExitFunction mThreadInitFunction = [](int) { };
76
InitExitFunction mThreadExitFunction = [](int) { };
77
78
/// Array of jobs (fixed size)
79
using AvailableJobs = FixedSizeFreeList<Job>;
80
AvailableJobs mJobs;
81
82
/// Threads running jobs
83
Array<thread> mThreads;
84
85
// The job queue
86
static constexpr uint32 cQueueLength = 1024;
87
static_assert(IsPowerOf2(cQueueLength)); // We do bit operations and require queue length to be a power of 2
88
atomic<Job *> mQueue[cQueueLength];
89
90
// Head and tail of the queue, do this value modulo cQueueLength - 1 to get the element in the mQueue array
91
atomic<uint> * mHeads = nullptr; ///< Per executing thread the head of the current queue
92
alignas(JPH_CACHE_LINE_SIZE) atomic<uint> mTail = 0; ///< Tail (write end) of the queue
93
94
// Semaphore used to signal worker threads that there is new work
95
Semaphore mSemaphore;
96
97
/// Boolean to indicate that we want to stop the job system
98
atomic<bool> mQuit = false;
99
};
100
101
JPH_NAMESPACE_END
102
103