OpenShot Library | OpenShotAudio  0.2.1
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  readWaitEvent.wait (100);
42 }
43 
44 bool ReadWriteLock::tryEnterRead() const noexcept
45 {
46  auto threadId = Thread::getCurrentThreadId();
47 
48  const SpinLock::ScopedLockType sl (accessLock);
49 
50  for (auto& readerThread : readerThreads)
51  {
52  if (readerThread.threadID == threadId)
53  {
54  readerThread.count++;
55  return true;
56  }
57  }
58 
59  if (numWriters + numWaitingWriters == 0
60  || (threadId == writerThreadId && numWriters > 0))
61  {
62  readerThreads.add ({ threadId, 1 });
63  return true;
64  }
65 
66  return false;
67 }
68 
69 void ReadWriteLock::exitRead() const noexcept
70 {
71  auto threadId = Thread::getCurrentThreadId();
72  const SpinLock::ScopedLockType sl (accessLock);
73 
74  for (int i = 0; i < readerThreads.size(); ++i)
75  {
76  auto& readerThread = readerThreads.getReference (i);
77 
78  if (readerThread.threadID == threadId)
79  {
80  if (--(readerThread.count) == 0)
81  {
82  readerThreads.remove (i);
83 
84  readWaitEvent.signal();
85  writeWaitEvent.signal();
86  }
87 
88  return;
89  }
90  }
91 
92  jassertfalse; // unlocking a lock that wasn't locked..
93 }
94 
95 //==============================================================================
96 void ReadWriteLock::enterWrite() const noexcept
97 {
98  auto threadId = Thread::getCurrentThreadId();
99  const SpinLock::ScopedLockType sl (accessLock);
100 
101  while (! tryEnterWriteInternal (threadId))
102  {
103  ++numWaitingWriters;
104  accessLock.exit();
105  writeWaitEvent.wait (100);
106  accessLock.enter();
107  --numWaitingWriters;
108  }
109 }
110 
111 bool ReadWriteLock::tryEnterWrite() const noexcept
112 {
113  const SpinLock::ScopedLockType sl (accessLock);
114  return tryEnterWriteInternal (Thread::getCurrentThreadId());
115 }
116 
117 bool ReadWriteLock::tryEnterWriteInternal (Thread::ThreadID threadId) const noexcept
118 {
119  if (readerThreads.size() + numWriters == 0
120  || threadId == writerThreadId
121  || (readerThreads.size() == 1 && readerThreads.getReference (0).threadID == threadId))
122  {
123  writerThreadId = threadId;
124  ++numWriters;
125  return true;
126  }
127 
128  return false;
129 }
130 
131 void ReadWriteLock::exitWrite() const noexcept
132 {
133  const SpinLock::ScopedLockType sl (accessLock);
134 
135  // check this thread actually had the lock..
136  jassert (numWriters > 0 && writerThreadId == Thread::getCurrentThreadId());
137 
138  if (--numWriters == 0)
139  {
140  writerThreadId = {};
141 
142  readWaitEvent.signal();
143  writeWaitEvent.signal();
144  }
145 }
146 
147 } // namespace juce
ReadWriteLock() noexcept
Creates a ReadWriteLock object.
void signal() const
Wakes up any threads that are currently waiting on this 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:1066
bool tryEnterRead() const noexcept
Tries to lock this object for reading.
bool tryEnterWrite() const noexcept
Tries to lock this object for writing.
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.
bool wait(int timeOutMilliseconds=-1) const
Suspends the calling thread until the event has been signalled.
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) 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.
void remove(int indexToRemove)
Removes an element from the array.
Definition: juce_Array.h:771
void exitRead() const noexcept
Releases the read-lock.