1#include "thread/seadReadWriteLock.h"
2#include "prim/seadScopedLock.h"
3#include "thread/seadThread.h"
4
5namespace sead
6{
7ReadWriteLock::ReadWriteLock() = default;
8
9ReadWriteLock::~ReadWriteLock() = default;
10
11void ReadWriteLock::readLock()
12{
13 ScopedLock<SemaphoreLock> lock(&mReadLock);
14
15 if (mNumReaders.increment() == 0)
16 mWriteLock.lock();
17}
18
19void ReadWriteLock::readUnlock()
20{
21 if (mNumReaders.decrement() == 1)
22 mWriteLock.unlock();
23}
24
25void ReadWriteLock::writeLock()
26{
27 Thread* current_thread = ThreadMgr::instance()->getCurrentThread();
28 if (mWriterThread != current_thread)
29 {
30 if (mNumWriters.increment() == 0)
31 mReadLock.lock();
32
33 mWriteLock.lock();
34 mWriterThread = current_thread;
35 }
36 ++mWritingThreadCount;
37}
38
39// NON_MATCHING: see SemaphoreLock::unlock
40void ReadWriteLock::writeUnlock()
41{
42 Thread* current_thread = ThreadMgr::instance()->getCurrentThread();
43 if (mWriterThread != current_thread)
44 {
45 SEAD_ASSERT_MSG(false, "This thread[%p] does not have the lock.", current_thread);
46 return;
47 }
48
49 if (!current_thread || mWritingThreadCount == 0 || int(mWritingThreadCount) < 0)
50 {
51 SEAD_ASSERT_MSG(
52 false,
53 "mWritingThreadCount[%d] must not be 0 and current_thread[%p] must not be nullptr",
54 mWritingThreadCount, current_thread);
55 return;
56 }
57
58 --mWritingThreadCount;
59 if (mWritingThreadCount == 0)
60 {
61 mWriterThread = nullptr;
62 mWriteLock.unlock();
63 if (mNumWriters.decrement() == 1)
64 mReadLock.unlock();
65 }
66}
67
68ReadWriteLock::SemaphoreLock::SemaphoreLock() = default;
69
70void ReadWriteLock::SemaphoreLock::lock()
71{
72 if (mLockCount.increment())
73 mSemaphore.lock();
74}
75
76void ReadWriteLock::SemaphoreLock::unlock()
77{
78 if (mLockCount.decrement() != 1)
79 mSemaphore.unlock();
80}
81} // namespace sead
82