44 jassert (instance ==
this || instance ==
nullptr);
59 : (std::numeric_limits<uint32>::max() - (
lastTime -
now)));
66 if (callbackArrived.
wait (0))
74 if (! callbackArrived.
wait (300))
98 while (! timers.empty())
100 auto& first = timers.front();
102 if (first.countdownMs > 0)
105 auto* timer = first.timer;
106 first.countdownMs = timer->timerPeriodMs;
107 shuffleTimerBackInQueue (0);
114 timer->timerCallback();
126 void callTimersSynchronously()
139 static inline void add (
Timer* tim)
noexcept
141 if (instance ==
nullptr)
142 instance =
new TimerThread();
144 instance->addTimer (tim);
147 static inline void remove (
Timer* tim)
noexcept
149 if (instance !=
nullptr)
150 instance->removeTimer (tim);
153 static inline void resetCounter (
Timer* tim)
noexcept
155 if (instance !=
nullptr)
156 instance->resetTimerCounter (tim);
159 static TimerThread* instance;
160 static LockType lock;
163 struct TimerCountdown
169 std::vector<TimerCountdown> timers;
171 WaitableEvent callbackArrived;
173 struct CallTimersMessage :
public MessageManager::MessageBase
175 CallTimersMessage() {}
177 void messageCallback()
override
179 if (instance !=
nullptr)
180 instance->callTimers();
185 void addTimer (
Timer* t)
189 jassert (std::find_if (timers.begin(), timers.end(),
190 [t](TimerCountdown i) { return i.timer == t; }) == timers.end());
192 auto pos = timers.size();
194 timers.push_back ({ t, t->timerPeriodMs });
195 t->positionInQueue = pos;
196 shuffleTimerForwardInQueue (pos);
200 void removeTimer (
Timer* t)
202 auto pos = t->positionInQueue;
203 auto lastIndex = timers.size() - 1;
205 jassert (pos <= lastIndex);
206 jassert (timers[pos].timer == t);
208 for (
auto i = pos; i < lastIndex; ++i)
210 timers[i] = timers[i + 1];
211 timers[i].timer->positionInQueue = i;
217 void resetTimerCounter (
Timer* t)
noexcept
219 auto pos = t->positionInQueue;
221 jassert (pos < timers.size());
222 jassert (timers[pos].timer == t);
224 auto lastCountdown = timers[pos].countdownMs;
225 auto newCountdown = t->timerPeriodMs;
227 if (newCountdown != lastCountdown)
229 timers[pos].countdownMs = newCountdown;
231 if (newCountdown > lastCountdown)
232 shuffleTimerBackInQueue (pos);
234 shuffleTimerForwardInQueue (pos);
240 void shuffleTimerBackInQueue (
size_t pos)
242 auto numTimers = timers.size();
244 if (pos < numTimers - 1)
246 auto t = timers[pos];
252 if (next == numTimers || timers[next].countdownMs >= t.countdownMs)
255 timers[pos] = timers[next];
256 timers[pos].timer->positionInQueue = pos;
262 t.timer->positionInQueue = pos;
266 void shuffleTimerForwardInQueue (
size_t pos)
270 auto t = timers[pos];
274 auto& prev = timers[(size_t) pos - 1];
276 if (prev.countdownMs <= t.countdownMs)
280 timers[pos].timer->positionInQueue = pos;
286 t.timer->positionInQueue = pos;
290 int getTimeUntilFirstTimer (
int numMillisecsElapsed)
297 for (
auto& t : timers)
298 t.countdownMs -= numMillisecsElapsed;
300 return timers.front().countdownMs;
303 void handleAsyncUpdate()
override
308 JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (TimerThread)