mirror of
https://github.com/juce-framework/JUCE.git
synced 2026-01-10 23:44:24 +00:00
More refactoring of Timer internals to reduce thread wake-up frequency
This commit is contained in:
parent
3e5ae4ea6a
commit
4b4d21682e
1 changed files with 22 additions and 44 deletions
|
|
@ -31,14 +31,15 @@ public:
|
|||
|
||||
TimerThread()
|
||||
: Thread ("Juce Timer"),
|
||||
firstTimer (nullptr),
|
||||
callbackNeeded (0)
|
||||
firstTimer (nullptr)
|
||||
{
|
||||
triggerAsyncUpdate();
|
||||
}
|
||||
|
||||
~TimerThread() noexcept
|
||||
{
|
||||
signalThreadShouldExit();
|
||||
callbackArrived.signal();
|
||||
stopThread (4000);
|
||||
|
||||
jassert (instance == this || instance == nullptr);
|
||||
|
|
@ -63,46 +64,29 @@ public:
|
|||
|
||||
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))
|
||||
if (callbackArrived.wait (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;
|
||||
}
|
||||
}
|
||||
// already a message in flight - do nothing..
|
||||
}
|
||||
else
|
||||
{
|
||||
wait (1);
|
||||
messageToSend->post();
|
||||
|
||||
if (! callbackArrived.wait (300))
|
||||
{
|
||||
// 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.
|
||||
messageToSend->post();
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
}
|
||||
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));
|
||||
}
|
||||
|
||||
// don't wait for too long because running this loop also helps keep the
|
||||
// Time::getApproximateMillisecondTimer value stay up-to-date
|
||||
wait (jlimit (1, 100, timeUntilFirstTimer));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -127,13 +111,7 @@ public:
|
|||
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);
|
||||
callbackArrived.signal();
|
||||
}
|
||||
|
||||
void callTimersSynchronously()
|
||||
|
|
@ -184,7 +162,7 @@ public:
|
|||
|
||||
private:
|
||||
Timer* volatile firstTimer;
|
||||
Atomic<int> callbackNeeded;
|
||||
WaitableEvent callbackArrived;
|
||||
|
||||
struct CallTimersMessage : public MessageManager::MessageBase
|
||||
{
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue