2 ==============================================================================
4 This file is part of the JUCE library - "Jules' Utility Class Extensions"
5 Copyright 2004-11 by Raw Material Software Ltd.
7 ------------------------------------------------------------------------------
9 JUCE can be redistributed and/or modified under the terms of the GNU General
10 Public License (Version 2), as published by the Free Software Foundation.
11 A copy of the license is included in the JUCE distribution, or can be found
12 online at www.gnu.org/licenses.
14 JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
15 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
16 A PARTICULAR PURPOSE. See the GNU General Public License for more details.
18 ------------------------------------------------------------------------------
20 To release a closed-source product which uses JUCE, commercial licenses are
21 available: visit www.rawmaterialsoftware.com/juce for more information.
23 ==============================================================================
26 #include "../core/juce_StandardHeader.h"
30 #include "juce_ReadWriteLock.h"
31 #include "juce_Thread.h"
34 //==============================================================================
35 ReadWriteLock::ReadWriteLock() noexcept
36 : numWaitingWriters (0),
42 ReadWriteLock::~ReadWriteLock() noexcept
44 jassert (readerThreads
.size() == 0);
45 jassert (numWriters
== 0);
48 //==============================================================================
49 void ReadWriteLock::enterRead() const noexcept
51 const Thread::ThreadID threadId
= Thread::getCurrentThreadId();
52 const SpinLock::ScopedLockType
sl (accessLock
);
56 jassert (readerThreads
.size() % 2 == 0);
59 for (i
= 0; i
< readerThreads
.size(); i
+= 2)
60 if (readerThreads
.getUnchecked(i
) == threadId
)
63 if (i
< readerThreads
.size()
64 || numWriters
+ numWaitingWriters
== 0
65 || (threadId
== writerThreadId
&& numWriters
> 0))
67 if (i
< readerThreads
.size())
69 readerThreads
.set (i
+ 1, (Thread::ThreadID
) (1 + (pointer_sized_int
) readerThreads
.getUnchecked (i
+ 1)));
73 readerThreads
.add (threadId
);
74 readerThreads
.add ((Thread::ThreadID
) 1);
80 const SpinLock::ScopedUnlockType
ul (accessLock
);
85 void ReadWriteLock::exitRead() const noexcept
87 const Thread::ThreadID threadId
= Thread::getCurrentThreadId();
88 const SpinLock::ScopedLockType
sl (accessLock
);
90 for (int i
= 0; i
< readerThreads
.size(); i
+= 2)
92 if (readerThreads
.getUnchecked(i
) == threadId
)
94 const pointer_sized_int newCount
= ((pointer_sized_int
) readerThreads
.getUnchecked (i
+ 1)) - 1;
98 readerThreads
.removeRange (i
, 2);
103 readerThreads
.set (i
+ 1, (Thread::ThreadID
) newCount
);
110 jassertfalse
; // unlocking a lock that wasn't locked..
113 //==============================================================================
114 void ReadWriteLock::enterWrite() const noexcept
116 const Thread::ThreadID threadId
= Thread::getCurrentThreadId();
117 const SpinLock::ScopedLockType
sl (accessLock
);
121 if (readerThreads
.size() + numWriters
== 0
122 || threadId
== writerThreadId
123 || (readerThreads
.size() == 2
124 && readerThreads
.getUnchecked(0) == threadId
))
126 writerThreadId
= threadId
;
133 waitEvent
.wait (100);
139 bool ReadWriteLock::tryEnterWrite() const noexcept
141 const Thread::ThreadID threadId
= Thread::getCurrentThreadId();
142 const SpinLock::ScopedLockType
sl (accessLock
);
144 if (readerThreads
.size() + numWriters
== 0
145 || threadId
== writerThreadId
146 || (readerThreads
.size() == 2
147 && readerThreads
.getUnchecked(0) == threadId
))
149 writerThreadId
= threadId
;
157 void ReadWriteLock::exitWrite() const noexcept
159 const SpinLock::ScopedLockType
sl (accessLock
);
161 // check this thread actually had the lock..
162 jassert (numWriters
> 0 && writerThreadId
== Thread::getCurrentThreadId());
164 if (--numWriters
== 0)