OpenShot Audio Library | OpenShotAudio 0.3.2

Loading...
Searching...
No Matches
juce_TimeSliceThread.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
26 TimeSliceThread::TimeSliceThread (const String& name) : Thread (name)
27{
28}
29
30 TimeSliceThread::~TimeSliceThread()
31{
32 stopThread (2000);
33}
34
35//==============================================================================
36 void TimeSliceThread::addTimeSliceClient (TimeSliceClient* const client, int millisecondsBeforeStarting)
37{
38 if (client != nullptr)
39 {
40 const ScopedLock sl (listLock);
41 client->nextCallTime = Time::getCurrentTime() + RelativeTime::milliseconds (millisecondsBeforeStarting);
42 clients.addIfNotAlreadyThere (client);
43 notify();
44 }
45}
46
47 void TimeSliceThread::removeTimeSliceClient (TimeSliceClient* const client)
48{
49 const ScopedLock sl1 (listLock);
50
51 // if there's a chance we're in the middle of calling this client, we need to
52 // also lock the outer lock..
53 if (clientBeingCalled == client)
54 {
55 const ScopedUnlock ul (listLock); // unlock first to get the order right..
56
57 const ScopedLock sl2 (callbackLock);
58 const ScopedLock sl3 (listLock);
59
60 clients.removeFirstMatchingValue (client);
61 }
62 else
63 {
64 clients.removeFirstMatchingValue (client);
65 }
66}
67
68 void TimeSliceThread::removeAllClients()
69{
70 for (;;)
71 {
72 if (auto* c = getClient (0))
73 removeTimeSliceClient (c);
74 else
75 break;
76 }
77}
78
79 void TimeSliceThread::moveToFrontOfQueue (TimeSliceClient* client)
80{
81 const ScopedLock sl (listLock);
82
83 if (clients.contains (client))
84 {
85 client->nextCallTime = Time::getCurrentTime();
86 notify();
87 }
88}
89
90 int TimeSliceThread::getNumClients() const
91{
92 return clients.size();
93}
94
95 TimeSliceClient* TimeSliceThread::getClient (const int i) const
96{
97 const ScopedLock sl (listLock);
98 return clients[i];
99}
100
101//==============================================================================
102 TimeSliceClient* TimeSliceThread::getNextClient (int index) const
103{
104 Time soonest;
105 TimeSliceClient* client = nullptr;
106
107 for (int i = clients.size(); --i >= 0;)
108 {
109 auto* c = clients.getUnchecked ((i + index) % clients.size());
110
111 if (client == nullptr || c->nextCallTime < soonest)
112 {
113 client = c;
114 soonest = c->nextCallTime;
115 }
116 }
117
118 return client;
119}
120
121 void TimeSliceThread::run()
122{
123 int index = 0;
124
125 while (! threadShouldExit())
126 {
127 int timeToWait = 500;
128
129 {
130 Time nextClientTime;
131 int numClients = 0;
132
133 {
134 const ScopedLock sl2 (listLock);
135
136 numClients = clients.size();
137 index = numClients > 0 ? ((index + 1) % numClients) : 0;
138
139 if (auto* firstClient = getNextClient (index))
140 nextClientTime = firstClient->nextCallTime;
141 }
142
143 if (numClients > 0)
144 {
145 auto now = Time::getCurrentTime();
146
147 if (nextClientTime > now)
148 {
149 timeToWait = (int) jmin ((int64) 500, (nextClientTime - now).inMilliseconds());
150 }
151 else
152 {
153 timeToWait = index == 0 ? 1 : 0;
154
155 const ScopedLock sl (callbackLock);
156
157 {
158 const ScopedLock sl2 (listLock);
159 clientBeingCalled = getNextClient (index);
160 }
161
162 if (clientBeingCalled != nullptr)
163 {
164 const int msUntilNextCall = clientBeingCalled->useTimeSlice();
165
166 const ScopedLock sl2 (listLock);
167
168 if (msUntilNextCall >= 0)
169 clientBeingCalled->nextCallTime = now + RelativeTime::milliseconds (msUntilNextCall);
170 else
171 clients.removeFirstMatchingValue (clientBeingCalled);
172
173 clientBeingCalled = nullptr;
174 }
175 }
176 }
177 }
178
179 if (timeToWait > 0)
180 wait (timeToWait);
181 }
182}
183
184} // namespace juce
juce::GenericScopedLock
Definition: juce_ScopedLock.h:55
juce::GenericScopedUnlock
Definition: juce_ScopedLock.h:126
juce::RelativeTime::milliseconds
static RelativeTime milliseconds(int milliseconds) noexcept
Definition: juce_RelativeTime.cpp:31
juce::String
Definition: juce_String.h:39
juce::Thread
Definition: juce_Thread.h:43
juce::Thread::wait
bool wait(int timeOutMilliseconds) const
Definition: juce_Thread.cpp:300
juce::Thread::threadShouldExit
bool threadShouldExit() const
Definition: juce_Thread.cpp:182
juce::Thread::stopThread
bool stopThread(int timeOutMilliseconds)
Definition: juce_Thread.cpp:213
juce::Thread::notify
void notify() const
Definition: juce_Thread.cpp:305
juce::TimeSliceClient
Definition: juce_TimeSliceThread.h:44
juce::TimeSliceClient::useTimeSlice
virtual int useTimeSlice()=0
juce::TimeSliceThread::getNumClients
int getNumClients() const
Definition: juce_TimeSliceThread.cpp:90
juce::TimeSliceThread::removeTimeSliceClient
void removeTimeSliceClient(TimeSliceClient *clientToRemove)
Definition: juce_TimeSliceThread.cpp:47
juce::TimeSliceThread::addTimeSliceClient
void addTimeSliceClient(TimeSliceClient *clientToAdd, int millisecondsBeforeStarting=0)
Definition: juce_TimeSliceThread.cpp:36
juce::TimeSliceThread::~TimeSliceThread
~TimeSliceThread() override
Definition: juce_TimeSliceThread.cpp:30
juce::TimeSliceThread::getClient
TimeSliceClient * getClient(int index) const
Definition: juce_TimeSliceThread.cpp:95
juce::TimeSliceThread::moveToFrontOfQueue
void moveToFrontOfQueue(TimeSliceClient *clientToMove)
Definition: juce_TimeSliceThread.cpp:79
juce::TimeSliceThread::removeAllClients
void removeAllClients()
Definition: juce_TimeSliceThread.cpp:68
juce::TimeSliceThread::run
void run() override
Definition: juce_TimeSliceThread.cpp:121
juce::TimeSliceThread::TimeSliceThread
TimeSliceThread(const String &threadName)
Definition: juce_TimeSliceThread.cpp:26
juce::Time
Definition: juce_Time.h:37
juce::Time::getCurrentTime
static Time JUCE_CALLTYPE getCurrentTime() noexcept
Definition: juce_Time.cpp:218