OpenShot Library | libopenshot-audio  0.2.0
juce_ReadWriteLock.cpp
1 /*
2  ==============================================================================
3 
4  This file is part of the JUCE library.
5  Copyright (c) 2017 - ROLI Ltd.
6 
7  JUCE is an open source library subject to commercial or open-source
8  licensing.
9 
10  The code included in this file is provided under the terms of the ISC license
11  http://www.isc.org/downloads/software-support-policy/isc-license. Permission
12  To use, copy, modify, and/or distribute this software for any purpose with or
13  without fee is hereby granted provided that the above copyright notice and
14  this permission notice appear in all copies.
15 
16  JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
17  EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
18  DISCLAIMED.
19 
20  ==============================================================================
21 */
22 
23 namespace juce
24 {
25 
27 {
28  readerThreads.ensureStorageAllocated (16);
29 }
30 
32 {
33  jassert (readerThreads.size() == 0);
34  jassert (numWriters == 0);
35 }
36 
37 //==============================================================================
38 void ReadWriteLock::enterRead() const noexcept
39 {
40  while (! tryEnterRead())
41  waitEvent.wait (100);
42 }
43 
44 bool ReadWriteLock::tryEnterRead() const noexcept
45 {
47 
48  const SpinLock::ScopedLockType sl (accessLock);
49 
50  for (int i = 0; i < readerThreads.size(); ++i)
51  {
52  ThreadRecursionCount& trc = readerThreads.getReference(i);
53 
54  if (trc.threadID == threadId)
55  {
56  trc.count++;
57  return true;
58  }
59  }
60 
61  if (numWriters + numWaitingWriters == 0
62  || (threadId == writerThreadId && numWriters > 0))
63  {
64  ThreadRecursionCount trc = { threadId, 1 };
65  readerThreads.add (trc);
66  return true;
67  }
68 
69  return false;
70 }
71 
72 void ReadWriteLock::exitRead() const noexcept
73 {
75  const SpinLock::ScopedLockType sl (accessLock);
76 
77  for (int i = 0; i < readerThreads.size(); ++i)
78  {
79  ThreadRecursionCount& trc = readerThreads.getReference(i);
80 
81  if (trc.threadID == threadId)
82  {
83  if (--(trc.count) == 0)
84  {
85  readerThreads.remove (i);
86  waitEvent.signal();
87  }
88 
89  return;
90  }
91  }
92 
93  jassertfalse; // unlocking a lock that wasn't locked..
94 }
95 
96 //==============================================================================
97 void ReadWriteLock::enterWrite() const noexcept
98 {
100  const SpinLock::ScopedLockType sl (accessLock);
101 
102  while (! tryEnterWriteInternal (threadId))
103  {
104  ++numWaitingWriters;
105  accessLock.exit();
106  waitEvent.wait (100);
107  accessLock.enter();
108  --numWaitingWriters;
109  }
110 }
111 
112 bool ReadWriteLock::tryEnterWrite() const noexcept
113 {
114  const SpinLock::ScopedLockType sl (accessLock);
115  return tryEnterWriteInternal (Thread::getCurrentThreadId());
116 }
117 
118 bool ReadWriteLock::tryEnterWriteInternal (Thread::ThreadID threadId) const noexcept
119 {
120  if (readerThreads.size() + numWriters == 0
121  || threadId == writerThreadId
122  || (readerThreads.size() == 1 && readerThreads.getReference(0).threadID == threadId))
123  {
124  writerThreadId = threadId;
125  ++numWriters;
126  return true;
127  }
128 
129  return false;
130 }
131 
132 void ReadWriteLock::exitWrite() const noexcept
133 {
134  const SpinLock::ScopedLockType sl (accessLock);
135 
136  // check this thread actually had the lock..
137  jassert (numWriters > 0 && writerThreadId == Thread::getCurrentThreadId());
138 
139  if (--numWriters == 0)
140  {
141  writerThreadId = {};
142  waitEvent.signal();
143  }
144 }
145 
146 } // namespace juce
ReadWriteLock() noexcept
Creates a ReadWriteLock object.
void exitWrite() const noexcept
Releases the write-lock.
void * ThreadID
A value type used for thread IDs.
Definition: juce_Thread.h:308
void ensureStorageAllocated(int minNumElements)
Increases the array&#39;s internal storage to hold a minimum number of elements.
Definition: juce_Array.h:1019
void add(const ElementType &newElement)
Appends a new element at the end of the array.
Definition: juce_Array.h:375
bool tryEnterRead() const noexcept
Tries to lock this object for reading.
bool tryEnterWrite() const noexcept
Tries to lock this object for writing.
void signal() const noexcept
Wakes up any threads that are currently waiting on this object.
static ThreadID JUCE_CALLTYPE getCurrentThreadId()
Returns an id that identifies the caller thread.
void enter() const noexcept
Acquires the lock.
void exit() const noexcept
Releases the lock.
Definition: juce_SpinLock.h:69
void enterRead() const noexcept
Locks this object for reading.
int size() const noexcept
Returns the current number of elements in the array.
Definition: juce_Array.h:219
void enterWrite() const noexcept
Locks this object for writing.
~ReadWriteLock() noexcept
Destructor.
ElementType & getReference(int index) const noexcept
Returns a direct reference to one of the elements in the array, without checking the index passed in...
Definition: juce_Array.h:271
Automatically locks and unlocks a mutex object.
bool wait(int timeOutMilliseconds=-1) const noexcept
Suspends the calling thread until the event has been signalled.
void remove(int indexToRemove)
Removes an element from the array.
Definition: juce_Array.h:724
void exitRead() const noexcept
Releases the read-lock.