juce中timer总体说还是比较好用的,使用时只需继承timer类, 重写callback然后调用start就可以了,juce的timer比较特别,自己通过线程实现,starttimer的时候会创建一个timerthread,然后在这个timerthread的构造函数中又触发了triggerAsyncUpdate(); 这样异步使线程start, 这样做是为了让timer对象添登记以后才开始线程,这也是常用技法, 然后在线程中检查定时是否到达,如果到达了的话就post消息,然后回调,只是这时其实已经在消息线程中了

    struct CallTimersMessage  : public MessageManager::MessageBase
{
CallTimersMessage() {} void messageCallback() override
{
if (instance != nullptr)
instance->callTimers();
}
};

  instance->callTimers(); 再调用各个timer的callback,也就是你重写的处理函数,大体就分析到这里,下次再进行一次仔细分析,前提条件没有准备充分,仔细分析太耗费时间。

/*
============================================================================== This file is part of the JUCE library.
Copyright (c) 2015 - ROLI 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)
{
triggerAsyncUpdate();
} ~TimerThread() noexcept
{
signalThreadShouldExit();
callbackArrived.signal();
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(); 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 (callbackArrived.wait (0))
{
// already a message in flight - do nothing..
}
else
{
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;
}
} // 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));
}
} void callTimers()
{
// avoid getting stuck in a loop if a timer callback repeatedly takes too long
const uint32 timeout = Time::getMillisecondCounter() + 100; const LockType::ScopedLockType sl (lock); while (firstTimer != nullptr && firstTimer->timerCountdownMs <= 0)
{
Timer* const t = firstTimer;
t->timerCountdownMs = t->timerPeriodMs; removeTimer (t);
addTimer (t); const LockType::ScopedUnlockType ul (lock); JUCE_TRY
{
t->timerCallback();
}
JUCE_CATCH_EXCEPTION if (Time::getMillisecondCounter() > timeout)
break;
} callbackArrived.signal();
} 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->timerCountdownMs = newCounter;
tim->timerPeriodMs = newCounter; if ((tim->nextTimer != nullptr && tim->nextTimer->timerCountdownMs < tim->timerCountdownMs)
|| (tim->previousTimer != nullptr && tim->previousTimer->timerCountdownMs > tim->timerCountdownMs))
{
instance->removeTimer (tim);
instance->addTimer (tim);
}
}
} static TimerThread* instance;
static LockType lock; private:
Timer* volatile firstTimer;
WaitableEvent callbackArrived; 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->timerCountdownMs > t->timerCountdownMs)
{
t->nextTimer = firstTimer;
firstTimer = t;
}
else
{
while (i->nextTimer != nullptr && i->nextTimer->timerCountdownMs <= t->timerCountdownMs)
i = i->nextTimer; jassert (i != nullptr); t->nextTimer = i->nextTimer;
t->previousTimer = i;
i->nextTimer = t;
} if (t->nextTimer != nullptr)
t->nextTimer->previousTimer = t; jassert ((t->nextTimer == nullptr || t->nextTimer->timerCountdownMs >= t->timerCountdownMs)
&& (t->previousTimer == nullptr || t->previousTimer->timerCountdownMs <= t->timerCountdownMs)); 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->previousTimer != nullptr)
{
jassert (firstTimer != t);
t->previousTimer->nextTimer = t->nextTimer;
}
else
{
jassert (firstTimer == t);
firstTimer = t->nextTimer;
} if (t->nextTimer != nullptr)
t->nextTimer->previousTimer = t->previousTimer; t->nextTimer = nullptr;
t->previousTimer = nullptr;
} int getTimeUntilFirstTimer (const int numMillisecsElapsed) const
{
const LockType::ScopedLockType sl (lock); for (Timer* t = firstTimer; t != nullptr; t = t->nextTimer)
t->timerCountdownMs -= numMillisecsElapsed; return firstTimer != nullptr ? firstTimer->timerCountdownMs : 1000;
} void handleAsyncUpdate() override
{
startThread (7);
} #if JUCE_DEBUG
bool timerExists (Timer* const t) const noexcept
{
for (Timer* tt = firstTimer; tt != nullptr; tt = tt->nextTimer)
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
: timerCountdownMs (0),
timerPeriodMs (0),
previousTimer (nullptr),
nextTimer (nullptr)
{
} Timer::Timer (const Timer&) noexcept
: timerCountdownMs (0),
timerPeriodMs (0),
previousTimer (nullptr),
nextTimer (nullptr)
{
} Timer::~Timer()
{
stopTimer();
} void Timer::startTimer (const int interval) noexcept
{
// If you're calling this before (or after) the MessageManager is
// running, then you're not going to get any timer callbacks!
jassert (MessageManager::getInstanceWithoutCreating() != nullptr); const TimerThread::LockType::ScopedLockType sl (TimerThread::lock); if (timerPeriodMs == 0)
{
timerCountdownMs = interval;
timerPeriodMs = jmax (1, interval);
TimerThread::add (this);
}
else
{
TimerThread::resetCounter (this, interval);
}
} void Timer::startTimerHz (int timerFrequencyHz) noexcept
{
if (timerFrequencyHz > 0)
startTimer (1000 / timerFrequencyHz);
else
stopTimer();
} void Timer::stopTimer() noexcept
{
const TimerThread::LockType::ScopedLockType sl (TimerThread::lock); if (timerPeriodMs > 0)
{
TimerThread::remove (this);
timerPeriodMs = 0;
}
} void JUCE_CALLTYPE Timer::callPendingTimersSynchronously()
{
if (TimerThread::instance != nullptr)
TimerThread::instance->callTimersSynchronously();
}

  

juce中的timer的更多相关文章

  1. iOS中的NSTimer 和 Android 中的Timer

    首先看iOS的, Scheduling Timers in Run Loops A timer object can be registered in only one run loop at a t ...

  2. .NET中的Timer类型用法详解

    这篇文章主要介绍了.NET中的Timer类型用法,较为详细的分析了Timer类型在各种环境下的用法,需要的朋友可以参考下   在.NET FrameWork中有多个Timer,那么怎么根据实际情况进行 ...

  3. 【JavaScript】JavaScript中的Timer是怎么工作的( setTimeout,setInterval)

    原文(http://www.yeeyan.org/articles/view/luosheng/24380) 作为入门者来说,了解JavaScript中timer的工作方式是很重要的.通常它们的表现行 ...

  4. juce中的BailOutChecker

    界面库中值得注意的一点就是对象响应事件的时候自身被删除了,那么后续的访问自然就会出问题,所以需要在响应事件之后先添加引用,相关处理之后再查看自身是否已经被删除,如果已经被删除那么就直接退出.juce中 ...

  5. juce 中的WeakReference分析

    juce中的WeakReference设计得比较巧妙,巧妙就是使用delete之后就可以通知道WeakReference,原理其实也很间单,其实就是在对象里添加了一个子对象masterReferenc ...

  6. ASP.NET AJAX入门系列(11):在多个UpdatePanle中使用Timer控件

    本文将使用Timer控件更新两个UpdatePanel控件,Timer控件将放在UpdatePanel控件的外面,并将它配置为UpdatePanel的触发器,翻译自官方文档. 主要内容 在多个Upda ...

  7. C# windows服务:C#windows服务中的Timer控件的使用

    C# windows服务程序中的Timer控件的使用问题是如何解决的呢? 今天和同事一起研究了下C# windows服务程序中的Timer控件的使用的写法. 我们在建立一个C# windows服务程序 ...

  8. Boost中的Timer的使用——计算时间流逝

    使用Boost中的Timer库计算程序的运行时间 程序开发人员都会面临一个共同的问题,即写出高质量的代码完毕特定的功能.评价代码质量的一个重要标准就是算法的运行效率,也就是算法的运行时间.为了可靠的提 ...

  9. Java中定时器Timer致命缺点(附学习方法)

    简介 这篇文章我一直在纠结到底要不要写,不想写一来因为定时器用法比较简单,二来是面试中也不常问.后来还是决定写了主要是想把自己分析问题思路分享给大家,让大家在学习过程中能够参考,学习态度我相信大部分人 ...

随机推荐

  1. ASP.net+SQL server2008简单的数据库增删改查 VS2012

    工具:VS2012 数据库:SQL server 简单说明:根据老师上课给的代码,进行了简单的改正适用于VS2012环境,包括注册.登录.查询.修改.删除功能,多数参考了网上的代码 百度云源代码连接t ...

  2. NSArray数组的学习总结

    1.不可变数组NSArray NSArray是不可变的,而且只能储存Object-c对象.另外,数组的最后一个元素一定是nil,表示结束. 注:这些集合类只能收集cocoa对象(NSOjbect对象) ...

  3. Java 基础之 static 静态

    static表示“全局”或者“静态”的意思,用来修饰成员变量和成员方法,也可以形成静态static代码块,但是Java语言中没有全局变量的概念. 被static修饰的成员变量和成员方法独立于该类的任何 ...

  4. Word Search II

    Given a 2D board and a list of words from the dictionary, find all words in the board. Each word mus ...

  5. Android studio Debug效率提升

    Android studio Debug效率提升,可以在控制台打印log的同时而不暂停程序的运行,尤其是当遇到复杂交互的时候,比如滑动,拖动,这时候程序暂停执行是特别恶心的.其实你可以更新打印信息而不 ...

  6. C# Winform程序本地化应用

    1. 创建一个WinForm应用程序 – “WindowsFormsLocalizationTest”. 2. 在主窗体属性栏里,把Localizable属性设置成”True”. 3. 添加两个But ...

  7. android的数据存储方式

    数据存储在开发中是使用最频繁的,在这里主要介绍Android平台中实现数据存储的5种方式,分别是: 1 使用SharedPreferences存储数据 2 文件存储数据 3 SQLite数据库存储数据 ...

  8. requirejs--源码分析

    /*---------------------------------------start-------------------------------*/ req({}); // num == 1 ...

  9. 【写一个自己的js库】 4.完善跨浏览器事件操作

    1.阻止冒泡. function stopPropagation(event){ event = event || getEvent(event); if(event.stopPropagation) ...

  10. delphi 把多个线程的请求阻塞到另一个线程 TElegantThread

    本例是把多个线程访问数据库的请求,全部阻塞到一个线程. 这是实际编程中常见的一种问题. 示例源码下载,所需支持单元均在源码中,且附详细说明. TElegantThread 的父类是 TSimpleTh ...