OpenShot Audio Library | OpenShotAudio 0.4.0
juce_TimeSliceThread.cpp
1/*
2 ==============================================================================
3
4 This file is part of the JUCE library.
5 Copyright (c) 2022 - Raw Material Software Limited
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
23namespace juce
24{
25
27{
28}
29
31{
32 stopThread (2000);
33}
34
35//==============================================================================
36void 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
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
69{
70 for (;;)
71 {
72 if (auto* c = getClient (0))
74 else
75 break;
76 }
77}
78
80{
81 const ScopedLock sl (listLock);
82
83 if (clients.contains (client))
84 {
85 client->nextCallTime = Time::getCurrentTime();
86 notify();
87 }
88}
89
91{
92 const ScopedLock sl (listLock);
93 return clients.size();
94}
95
97{
98 const ScopedLock sl (listLock);
99 return clients[i];
100}
101
103{
104 const ScopedLock sl (listLock);
105 return std::any_of (clients.begin(), clients.end(), [=] (auto* registered) { return registered == c; });
106}
107
108//==============================================================================
109TimeSliceClient* TimeSliceThread::getNextClient (int index) const
110{
111 Time soonest;
112 TimeSliceClient* client = nullptr;
113
114 for (int i = clients.size(); --i >= 0;)
115 {
116 auto* c = clients.getUnchecked ((i + index) % clients.size());
117
118 if (c != nullptr && (client == nullptr || c->nextCallTime < soonest))
119 {
120 client = c;
121 soonest = c->nextCallTime;
122 }
123 }
124
125 return client;
126}
127
129{
130 int index = 0;
131
132 while (! threadShouldExit())
133 {
134 int timeToWait = 500;
135
136 {
137 Time nextClientTime;
138 int numClients = 0;
139
140 {
141 const ScopedLock sl2 (listLock);
142
143 numClients = clients.size();
144 index = numClients > 0 ? ((index + 1) % numClients) : 0;
145
146 if (auto* firstClient = getNextClient (index))
147 nextClientTime = firstClient->nextCallTime;
148 }
149
150 if (numClients > 0)
151 {
152 auto now = Time::getCurrentTime();
153
154 if (nextClientTime > now)
155 {
156 timeToWait = (int) jmin ((int64) 500, (nextClientTime - now).inMilliseconds());
157 }
158 else
159 {
160 timeToWait = index == 0 ? 1 : 0;
161
162 const ScopedLock sl (callbackLock);
163
164 {
165 const ScopedLock sl2 (listLock);
166 clientBeingCalled = getNextClient (index);
167 }
168
169 if (clientBeingCalled != nullptr)
170 {
171 const int msUntilNextCall = clientBeingCalled->useTimeSlice();
172
173 const ScopedLock sl2 (listLock);
174
175 if (msUntilNextCall >= 0)
176 clientBeingCalled->nextCallTime = now + RelativeTime::milliseconds (msUntilNextCall);
177 else
178 clients.removeFirstMatchingValue (clientBeingCalled);
179
180 clientBeingCalled = nullptr;
181 }
182 }
183 }
184 }
185
186 if (timeToWait > 0)
187 wait (timeToWait);
188 }
189}
190
191} // namespace juce
static RelativeTime milliseconds(int milliseconds) noexcept
bool wait(double timeOutMilliseconds) const
bool threadShouldExit() const
bool stopThread(int timeOutMilliseconds)
void notify() const
virtual int useTimeSlice()=0
void removeTimeSliceClient(TimeSliceClient *clientToRemove)
void addTimeSliceClient(TimeSliceClient *clientToAdd, int millisecondsBeforeStarting=0)
TimeSliceClient * getClient(int index) const
void moveToFrontOfQueue(TimeSliceClient *clientToMove)
bool contains(const TimeSliceClient *) const
TimeSliceThread(const String &threadName)
static Time JUCE_CALLTYPE getCurrentTime() noexcept
Definition: juce_Time.cpp:233