1#include <framework/seadMethodTree.h>
2#include <thread/seadCriticalSection.h>
3
4namespace sead
5{
6void MethodTreeNode::pushBackChild(MethodTreeNode* node)
7{
8 lock_();
9 node->detachSubTree();
10 node->mCriticalSection = mCriticalSection;
11 if (node->child())
12 {
13 auto* parent = node->child()->value();
14 if (parent)
15 parent->attachMutexRec_(m: mCriticalSection);
16 }
17 TreeNode::pushBackChild(node);
18 unlock_();
19}
20
21void MethodTreeNode::pushFrontChild(MethodTreeNode* node)
22{
23 lock_();
24 node->detachSubTree();
25 node->mCriticalSection = mCriticalSection;
26 if (node->child())
27 {
28 auto* parent = node->child()->value();
29 if (parent)
30 parent->attachMutexRec_(m: mCriticalSection);
31 }
32 TreeNode::pushFrontChild(node);
33 unlock_();
34}
35
36void MethodTreeNode::attachMutexRec_(CriticalSection* m) const
37{
38 const MethodTreeNode* node = this;
39
40 do
41 {
42 auto* child = node->child();
43 node->mCriticalSection = m;
44 if (child && child->value())
45 child->value()->attachMutexRec_(m);
46 } while (node->next() && (node = node->next()->value()));
47}
48
49void MethodTreeNode::detachAll()
50{
51 CriticalSection* cs = mCriticalSection;
52 attachMutexRec_(NULL);
53 mCriticalSection = cs;
54
55 lock_();
56 TreeNode::detachAll();
57 unlock_();
58
59 mCriticalSection = NULL;
60}
61
62void MethodTreeNode::lock_()
63{
64 if (mCriticalSection == NULL)
65 return;
66
67 mCriticalSection->lock();
68}
69
70void MethodTreeNode::unlock_()
71{
72 if (mCriticalSection == NULL)
73 return;
74
75 mCriticalSection->unlock();
76}
77
78void MethodTreeNode::call()
79{
80 lock_();
81 callRec_();
82 unlock_();
83}
84
85void MethodTreeNode::callRec_()
86{
87 if (!mPauseFlag.isOn(val: cPause_Self))
88 (*mDelegateHolder.data())();
89
90 auto* node = child();
91 if (node && !mPauseFlag.isOn(val: cPause_Child))
92 {
93 while (node)
94 {
95 node->value()->callRec_();
96 node = node->value()->next();
97 }
98 }
99}
100
101} // namespace sead
102