OpenShot Audio Library | OpenShotAudio  0.3.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  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
void exitWrite() const noexcept
void * ThreadID
Definition: juce_Thread.h:304
void ensureStorageAllocated(int minNumElements)
Definition: juce_Array.h:1062
bool tryEnterRead() const noexcept
bool tryEnterWrite() const noexcept
static ThreadID JUCE_CALLTYPE getCurrentThreadId()
void enter() const noexcept
void exit() const noexcept
Definition: juce_SpinLock.h:65
void enterRead() const noexcept
bool wait(int timeOutMilliseconds=-1) const
int size() const noexcept
Definition: juce_Array.h:215
void enterWrite() const noexcept
ElementType & getReference(int index) noexcept
Definition: juce_Array.h:267
void remove(int indexToRemove)
Definition: juce_Array.h:767
void exitRead() const noexcept