1#pragma once
2
3#include "basis/seadTypes.h"
4#include "container/seadBuffer.h"
5#include "container/seadSafeArray.h"
6#include "framework/seadProcessMeterBar.h"
7#include "hostio/seadHostIONode.h"
8#include "mc/seadCoreInfo.h"
9#include "mc/seadJob.h"
10#include "prim/seadEnum.h"
11#include "prim/seadNamable.h"
12#include "thread/seadAtomic.h"
13#include "thread/seadEvent.h"
14
15namespace sead
16{
17class Heap;
18class Worker;
19
20SEAD_ENUM(SyncType, cNoSync, cCore, cThread)
21
22class PerfJobQueue
23{
24public:
25 void initialize(const char* name, Heap* heap);
26 void finalize();
27 void reset();
28
29 void measureBeginDeque();
30 void measureEndDeque();
31 void measureBeginRun();
32 void measureEndRun();
33
34 const Color4f& getBarColor(u32 idx) const;
35 void attachProcessMeter();
36 void detachProcessMeter();
37
38private:
39 Buffer<MultiProcessMeterBar<512>> mBars;
40 Buffer<u32> mInts;
41 MultiProcessMeterBar<1> mProcessMeterBar;
42};
43
44class JobQueueLock
45{
46public:
47 void lock()
48 {
49 while (mSpinLock.load() == 1)
50 continue;
51 while (!mSpinLock.compareExchange(expected: 0, desired: 1))
52 continue;
53 }
54
55 void unlock()
56 {
57 std::atomic_thread_fence(m: std::memory_order_seq_cst);
58 while (!mSpinLock.compareExchange(expected: 1, desired: 0))
59 continue;
60 }
61
62private:
63 Atomic<u32> mSpinLock = 0;
64};
65
66class JobQueue : public hostio::Node, public INamable
67{
68public:
69 enum class Status : int
70 {
71 _0 = 0,
72 _1 = 1,
73 _3 = 3,
74 _5 = 5,
75 _6 = 6,
76 };
77
78 JobQueue();
79
80 virtual void begin() {}
81 virtual bool run(u32 size, u32* finished_jobs, Worker* worker);
82 void runAll(u32* finished_jobs);
83
84 virtual u32 getNumJobs() const { return 0; }
85 bool isAllParticipantThrough() const;
86
87 u32 getGranularity(u32 core) { return mGranularity[core]; }
88 void setGranularity(CoreId core, u32 x);
89 void setGranularity(u32);
90 void setCoreMaskAndWaitType(CoreIdMask mask, SyncType type);
91
92 void FINISH(CoreId core);
93 void wait_AT_WORKER();
94 void wait();
95
96 const char* getDescription() const { return mDescription; }
97 void setDescription(const char* description) { mDescription = description; }
98
99 void signalFinishEvent() { mFinishEvent.setSignal(); }
100 void resetFinishEvent() { mFinishEvent.resetSignal(); }
101 u32 addNumDoneJobs(u32 num) { return mNumDoneJobs.fetchAdd(x: num); }
102
103protected:
104 virtual bool isDone_();
105
106 SyncType mSyncType = SyncType::cNoSync;
107 JobQueueLock mLock;
108 CoreIdMask mMask;
109 Event mFinishEvent{true};
110 SafeArray<u32, 3> mGranularity;
111 SafeArray<u32, 3> mCoreEnabled;
112 Atomic<u32> mNumDoneJobs = 0;
113
114 Atomic<Status> mStatus = Status::_0;
115 const char* mDescription = "NoName";
116
117#ifdef SEAD_DEBUG
118 PerfJobQueue mPerf;
119#endif
120};
121
122class FixedSizeJQ : public JobQueue
123{
124public:
125 FixedSizeJQ();
126
127#ifdef SEAD_DEBUG
128 void listenPropertyEvent(const hostio::PropertyEvent* event) override;
129 void genMessage(hostio::Context* context) override;
130#endif
131
132 void begin() override;
133 bool run(u32 size, u32* finished_jobs, Worker* worker) override;
134 u32 getNumJobs() const override;
135
136 void initialize(u32 size, Heap* heap);
137 void finalize();
138
139 bool enque(Job* job);
140 bool enqueSafe(Job* job);
141 Job* deque();
142 u32 deque(Job** jobs, u32 count);
143 bool rewind();
144 void clear();
145
146 bool debug_IsAllJobDone();
147
148protected:
149 Buffer<Job*> mJobs;
150 u32 mNumJobs;
151 u32 mNumProcessedJobs;
152 bool _230;
153};
154} // namespace sead
155