| 
							- /*
 -   ==============================================================================
 - 
 -    This file is part of the JUCE library.
 -    Copyright (c) 2013 - Raw Material Software Ltd.
 - 
 -    Permission is granted to use this software under the terms of either:
 -    a) the GPL v2 (or any later version)
 -    b) the Affero GPL v3
 - 
 -    Details of these licenses can be found at: www.gnu.org/licenses
 - 
 -    JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
 -    WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 -    A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
 - 
 -    ------------------------------------------------------------------------------
 - 
 -    To release a closed-source product which uses JUCE, commercial licenses are
 -    available: visit www.juce.com for more information.
 - 
 -   ==============================================================================
 - */
 - 
 - class Timer::TimerThread  : private Thread,
 -                             private DeletedAtShutdown,
 -                             private AsyncUpdater
 - {
 - public:
 -     typedef CriticalSection LockType; // (mysteriously, using a SpinLock here causes problems on some XP machines..)
 - 
 -     TimerThread()
 -         : Thread ("Juce Timer"),
 -           firstTimer (nullptr),
 -           callbackNeeded (0)
 -     {
 -         triggerAsyncUpdate();
 -     }
 - 
 -     ~TimerThread() noexcept
 -     {
 -         stopThread (4000);
 - 
 -         jassert (instance == this || instance == nullptr);
 -         if (instance == this)
 -             instance = nullptr;
 -     }
 - 
 -     void run() override
 -     {
 -         uint32 lastTime = Time::getMillisecondCounter();
 -         MessageManager::MessageBase::Ptr messageToSend (new CallTimersMessage());
 - 
 -         while (! threadShouldExit())
 -         {
 -             const uint32 now = Time::getMillisecondCounter();
 - 
 -             if (now == lastTime)
 -             {
 -                 wait (1);
 -                 continue;
 -             }
 - 
 -             const int elapsed = (int) (now >= lastTime ? (now - lastTime)
 -                                                        : (std::numeric_limits<uint32>::max() - (lastTime - now)));
 -             lastTime = now;
 - 
 -             const int timeUntilFirstTimer = getTimeUntilFirstTimer (elapsed);
 - 
 -             if (timeUntilFirstTimer <= 0)
 -             {
 -                 /* If we managed to set the atomic boolean to true then send a message, this is needed
 -                    as a memory barrier so the message won't be sent before callbackNeeded is set to true,
 -                    but if it fails it means the message-thread changed the value from under us so at least
 -                    some processing is happenening and we can just loop around and try again
 -                 */
 -                 if (callbackNeeded.compareAndSetBool (1, 0))
 -                 {
 -                     messageToSend->post();
 - 
 -                     /* Sometimes our message can get discarded by the OS (e.g. when running as an RTAS
 -                        when the app has a modal loop), so this is how long to wait before assuming the
 -                        message has been lost and trying again.
 -                     */
 -                     const uint32 messageDeliveryTimeout = now + 300;
 - 
 -                     while (callbackNeeded.get() != 0)
 -                     {
 -                         wait (4);
 - 
 -                         if (threadShouldExit())
 -                             return;
 - 
 -                         if (Time::getMillisecondCounter() > messageDeliveryTimeout)
 -                         {
 -                             messageToSend->post();
 -                             break;
 -                         }
 -                     }
 -                 }
 -             }
 -             else
 -             {
 -                 // don't wait for too long because running this loop also helps keep the
 -                 // Time::getApproximateMillisecondTimer value stay up-to-date
 -                 wait (jlimit (1, 50, timeUntilFirstTimer));
 -             }
 -         }
 -     }
 - 
 -     void callTimers()
 -     {
 -         const LockType::ScopedLockType sl (lock);
 - 
 -         while (firstTimer != nullptr && firstTimer->countdownMs <= 0)
 -         {
 -             Timer* const t = firstTimer;
 -             t->countdownMs = t->periodMs;
 - 
 -             removeTimer (t);
 -             addTimer (t);
 - 
 -             const LockType::ScopedUnlockType ul (lock);
 - 
 -             JUCE_TRY
 -             {
 -                 t->timerCallback();
 -             }
 -             JUCE_CATCH_EXCEPTION
 -         }
 - 
 -         /* This is needed as a memory barrier to make sure all processing of current timers is done
 -            before the boolean is set. This set should never fail since if it was false in the first place,
 -            we wouldn't get a message (so it can't be changed from false to true from under us), and if we
 -            get a message then the value is true and the other thread can only set it to true again and
 -            we will get another callback to set it to false.
 -         */
 -         callbackNeeded.set (0);
 -     }
 - 
 -     void callTimersSynchronously()
 -     {
 -         if (! isThreadRunning())
 -         {
 -             // (This is relied on by some plugins in cases where the MM has
 -             // had to restart and the async callback never started)
 -             cancelPendingUpdate();
 -             triggerAsyncUpdate();
 -         }
 - 
 -         callTimers();
 -     }
 - 
 -     static inline void add (Timer* const tim) noexcept
 -     {
 -         if (instance == nullptr)
 -             instance = new TimerThread();
 - 
 -         instance->addTimer (tim);
 -     }
 - 
 -     static inline void remove (Timer* const tim) noexcept
 -     {
 -         if (instance != nullptr)
 -             instance->removeTimer (tim);
 -     }
 - 
 -     static inline void resetCounter (Timer* const tim, const int newCounter) noexcept
 -     {
 -         if (instance != nullptr)
 -         {
 -             tim->countdownMs = newCounter;
 -             tim->periodMs = newCounter;
 - 
 -             if ((tim->next != nullptr && tim->next->countdownMs < tim->countdownMs)
 -                  || (tim->previous != nullptr && tim->previous->countdownMs > tim->countdownMs))
 -             {
 -                 instance->removeTimer (tim);
 -                 instance->addTimer (tim);
 -             }
 -         }
 -     }
 - 
 -     static TimerThread* instance;
 -     static LockType lock;
 - 
 - private:
 -     Timer* volatile firstTimer;
 -     Atomic <int> callbackNeeded;
 - 
 -     struct CallTimersMessage  : public MessageManager::MessageBase
 -     {
 -         CallTimersMessage() {}
 - 
 -         void messageCallback() override
 -         {
 -             if (instance != nullptr)
 -                 instance->callTimers();
 -         }
 -     };
 - 
 -     //==============================================================================
 -     void addTimer (Timer* const t) noexcept
 -     {
 -        #if JUCE_DEBUG
 -         // trying to add a timer that's already here - shouldn't get to this point,
 -         // so if you get this assertion, let me know!
 -         jassert (! timerExists (t));
 -        #endif
 - 
 -         Timer* i = firstTimer;
 - 
 -         if (i == nullptr || i->countdownMs > t->countdownMs)
 -         {
 -             t->next = firstTimer;
 -             firstTimer = t;
 -         }
 -         else
 -         {
 -             while (i->next != nullptr && i->next->countdownMs <= t->countdownMs)
 -                 i = i->next;
 - 
 -             jassert (i != nullptr);
 - 
 -             t->next = i->next;
 -             t->previous = i;
 -             i->next = t;
 -         }
 - 
 -         if (t->next != nullptr)
 -             t->next->previous = t;
 - 
 -         jassert ((t->next == nullptr || t->next->countdownMs >= t->countdownMs)
 -                   && (t->previous == nullptr || t->previous->countdownMs <= t->countdownMs));
 - 
 -         notify();
 -     }
 - 
 -     void removeTimer (Timer* const t) noexcept
 -     {
 -        #if JUCE_DEBUG
 -         // trying to remove a timer that's not here - shouldn't get to this point,
 -         // so if you get this assertion, let me know!
 -         jassert (timerExists (t));
 -        #endif
 - 
 -         if (t->previous != nullptr)
 -         {
 -             jassert (firstTimer != t);
 -             t->previous->next = t->next;
 -         }
 -         else
 -         {
 -             jassert (firstTimer == t);
 -             firstTimer = t->next;
 -         }
 - 
 -         if (t->next != nullptr)
 -             t->next->previous = t->previous;
 - 
 -         t->next = nullptr;
 -         t->previous = nullptr;
 -     }
 - 
 -     int getTimeUntilFirstTimer (const int numMillisecsElapsed) const
 -     {
 -         const LockType::ScopedLockType sl (lock);
 - 
 -         for (Timer* t = firstTimer; t != nullptr; t = t->next)
 -             t->countdownMs -= numMillisecsElapsed;
 - 
 -         return firstTimer != nullptr ? firstTimer->countdownMs : 1000;
 -     }
 - 
 -     void handleAsyncUpdate() override
 -     {
 -         startThread (7);
 -     }
 - 
 -    #if JUCE_DEBUG
 -     bool timerExists (Timer* const t) const noexcept
 -     {
 -         for (Timer* tt = firstTimer; tt != nullptr; tt = tt->next)
 -             if (tt == t)
 -                 return true;
 - 
 -         return false;
 -     }
 -    #endif
 - 
 -     JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (TimerThread)
 - };
 - 
 - Timer::TimerThread* Timer::TimerThread::instance = nullptr;
 - Timer::TimerThread::LockType Timer::TimerThread::lock;
 - 
 - //==============================================================================
 - Timer::Timer() noexcept
 -    : countdownMs (0),
 -      periodMs (0),
 -      previous (nullptr),
 -      next (nullptr)
 - {
 - }
 - 
 - Timer::Timer (const Timer&) noexcept
 -    : countdownMs (0),
 -      periodMs (0),
 -      previous (nullptr),
 -      next (nullptr)
 - {
 - }
 - 
 - Timer::~Timer()
 - {
 -     stopTimer();
 - }
 - 
 - void Timer::startTimer (const int interval) noexcept
 - {
 -     const TimerThread::LockType::ScopedLockType sl (TimerThread::lock);
 - 
 -     if (periodMs == 0)
 -     {
 -         countdownMs = interval;
 -         periodMs = jmax (1, interval);
 -         TimerThread::add (this);
 -     }
 -     else
 -     {
 -         TimerThread::resetCounter (this, interval);
 -     }
 - }
 - 
 - void Timer::stopTimer() noexcept
 - {
 -     const TimerThread::LockType::ScopedLockType sl (TimerThread::lock);
 - 
 -     if (periodMs > 0)
 -     {
 -         TimerThread::remove (this);
 -         periodMs = 0;
 -     }
 - }
 - 
 - void JUCE_CALLTYPE Timer::callPendingTimersSynchronously()
 - {
 -     if (TimerThread::instance != nullptr)
 -         TimerThread::instance->callTimersSynchronously();
 - }
 
 
  |