1#ifndef SEAD_METHODTREE_H_
2#define SEAD_METHODTREE_H_
3
4#include <container/seadTreeNode.h>
5#include <heap/seadDisposer.h>
6#include <prim/seadBitFlag.h>
7#include <prim/seadDelegate.h>
8#include <prim/seadNamable.h>
9#include <prim/seadRuntimeTypeInfo.h>
10#include <prim/seadStorageFor.h>
11
12namespace sead
13{
14class CriticalSection;
15
16template <typename T, typename U>
17class IDelegate2;
18
19class MethodTreeNode : public IDisposer, public TTreeNode<MethodTreeNode*>, public INamable
20{
21 SEAD_RTTI_BASE(MethodTreeNode)
22
23public:
24 enum PauseFlag
25 {
26 cPause_None = 0,
27 cPause_Self = 1,
28 cPause_Child = 2,
29 cPause_Both = 3,
30 };
31
32 using PauseEventDelegate = IDelegate2<MethodTreeNode*, PauseFlag>;
33
34 // NON_MATCHING: stores for mPauseFlag, mPauseEventDelegate, mUserID
35 explicit MethodTreeNode(CriticalSection* cs) : TTreeNode(this)
36 {
37 mCriticalSection = cs;
38 mPauseEventDelegate = nullptr;
39 mUserID = nullptr;
40 mDelegateHolder.construct(args: sead::Delegate<MethodTreeNode>());
41 setPauseFlag(cPause_Both);
42 }
43
44 ~MethodTreeNode() override { detachAll(); }
45
46 template <typename Delegate>
47 void bind(const Delegate& delegate, const char* name)
48 {
49 lock_();
50 mDelegateHolder.construct(delegate);
51 unlock_();
52
53 if (name)
54 setName(name);
55 }
56
57 void call();
58 void detachAll();
59 void pushBackChild(MethodTreeNode* node);
60 void pushFrontChild(MethodTreeNode* node);
61
62 void setPauseFlag(PauseFlag flag)
63 {
64 lock_();
65 if (mPauseEventDelegate)
66 mPauseEventDelegate->invoke(a1: this, a2: flag);
67 mPauseFlag = flag;
68 unlock_();
69 }
70
71private:
72 void attachMutexRec_(CriticalSection* m) const;
73 void callRec_();
74
75 void lock_();
76 void unlock_();
77
78 StorageFor<sead::AnyDelegate> mDelegateHolder;
79 mutable CriticalSection* mCriticalSection;
80 [[maybe_unused]] u32 mPriority;
81 BitFlag32 mPauseFlag;
82 PauseEventDelegate* mPauseEventDelegate;
83 void* mUserID;
84};
85
86} // namespace sead
87
88#endif // SEAD_METHODTREE_H_
89