summaryrefslogtreecommitdiff
path: root/src/KingSystem/Utils/Thread/TaskThread.h
diff options
context:
space:
mode:
authorLéo Lam <leo@leolam.fr>2020-09-10 22:11:27 +0200
committerLéo Lam <leo@leolam.fr>2020-09-15 17:54:16 +0200
commit8b7369dffb1e816b2f27ab0133d2bac218383a45 (patch)
treec5d6a577ec9102e65a6e08272432dfa862670a60 /src/KingSystem/Utils/Thread/TaskThread.h
parentc5ef0a1fd3629a27dc2fc7de7a46347c6cb3518e (diff)
ksys: Add Task utilities
Diffstat (limited to 'src/KingSystem/Utils/Thread/TaskThread.h')
-rw-r--r--src/KingSystem/Utils/Thread/TaskThread.h109
1 files changed, 109 insertions, 0 deletions
diff --git a/src/KingSystem/Utils/Thread/TaskThread.h b/src/KingSystem/Utils/Thread/TaskThread.h
new file mode 100644
index 00000000..8d2cb559
--- /dev/null
+++ b/src/KingSystem/Utils/Thread/TaskThread.h
@@ -0,0 +1,109 @@
+#pragma once
+
+#include <prim/seadRuntimeTypeInfo.h>
+#include <prim/seadTypedBitFlag.h>
+#include <thread/seadAtomic.h>
+#include <thread/seadThread.h>
+#include "KingSystem/Utils/Thread/Event.h"
+#include "KingSystem/Utils/Types.h"
+
+namespace ksys::util {
+
+class Task;
+class TaskQueueBase;
+class TaskQueueLock;
+
+class TaskThread : public sead::Thread {
+ SEAD_RTTI_BASE(TaskThread)
+public:
+ enum Message {
+ cMessage_QueueUpdated = 1,
+ cMessage_Pause = 2,
+ cMessage_Resume = 3,
+ };
+
+ struct InitArg {
+ /// Number of lanes if a new queue is to be created.
+ /// Only used if queue is nullptr.
+ u16 num_lanes;
+ /// Number of tasks to process in a row before yielding. Can be zero to disable the limit.
+ u32 batch_size;
+ /// Heap that will be used to allocate a new queue if necessary.
+ /// Only used if queue is nullptr.
+ sead::Heap* heap;
+ /// Task queue. If null, a new queue will be created and owned by this thread.
+ TaskQueueBase* queue;
+ };
+ KSYS_CHECK_SIZE_NX150(InitArg, 0x18);
+
+ TaskThread(const sead::SafeString& name, sead::Heap* heap, s32 priority,
+ sead::MessageQueue::BlockType block_type, sead::MessageQueue::Element quit_msg,
+ s32 stack_size, s32 message_queue_size);
+ ~TaskThread() override;
+
+ bool init(const InitArg& arg);
+
+ s32 getNumActiveTasks() const;
+
+ void waitForQueueToEmpty();
+ void cancelTasks(u8 id);
+ void clearQueue();
+ void lock(TaskQueueLock* lock);
+
+ bool isActiveAndReceivedQueueUpdateMsg() const;
+ bool isPaused() const;
+ bool receivedQueueUpdatedMsg() const;
+
+ void pause();
+ void pauseAndWaitForAck();
+ void resume();
+ void resumeAndWaitForAck();
+
+ bool isBusyProcessingTask() const;
+ bool isLookingForTask() const;
+
+ bool receivedPauseMsg() const;
+ bool receivedResumeMsg() const;
+ bool receivedQuitMsg() const;
+
+ void cancelCurrentTask();
+
+ TaskQueueBase* getTaskQueue() const { return mTaskQueue; }
+
+protected:
+ friend class TaskQueueBase;
+
+ enum class Flag {
+ _1 = 0x1,
+ _2 = 0x2,
+ _4 = 0x4,
+ Paused = 0x8,
+ /// The task queue is *not* owned by this TaskThread.
+ DoesNotOwnTaskQueue = 0x10,
+ /// A batch is being processed.
+ IsActive = 0x20,
+ /// This thread is looking for a task to process.
+ IsLookingForTask = 0x40,
+ /// A task is being processed.
+ IsBusyProcessingTask = 0x80,
+ };
+
+ void calc_(sead::MessageQueue::Element msg) override;
+
+ sead::TypedBitFlag<Flag, u8> mFlags = [] {
+ decltype(mFlags) flags;
+ flags.set(Flag::_2);
+ flags.set(Flag::_4);
+ return flags;
+ }();
+ Task* mTask = nullptr;
+ s32 mBatchSize = 0;
+ s32 mNumRemainingTasksInBatch = 0;
+ sead::Atomic<Message> mPauseResumeMsg = cMessage_Resume;
+ Event mPauseResumeEvent;
+ Event mTaskProcessedEvent;
+ TaskQueueBase* mTaskQueue = nullptr;
+};
+KSYS_CHECK_SIZE_NX150(TaskThread, 0x1a0);
+
+} // namespace ksys::util