juce中的timer
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的更多相关文章
- iOS中的NSTimer 和 Android 中的Timer
首先看iOS的, Scheduling Timers in Run Loops A timer object can be registered in only one run loop at a t ...
- .NET中的Timer类型用法详解
这篇文章主要介绍了.NET中的Timer类型用法,较为详细的分析了Timer类型在各种环境下的用法,需要的朋友可以参考下 在.NET FrameWork中有多个Timer,那么怎么根据实际情况进行 ...
- 【JavaScript】JavaScript中的Timer是怎么工作的( setTimeout,setInterval)
原文(http://www.yeeyan.org/articles/view/luosheng/24380) 作为入门者来说,了解JavaScript中timer的工作方式是很重要的.通常它们的表现行 ...
- juce中的BailOutChecker
界面库中值得注意的一点就是对象响应事件的时候自身被删除了,那么后续的访问自然就会出问题,所以需要在响应事件之后先添加引用,相关处理之后再查看自身是否已经被删除,如果已经被删除那么就直接退出.juce中 ...
- juce 中的WeakReference分析
juce中的WeakReference设计得比较巧妙,巧妙就是使用delete之后就可以通知道WeakReference,原理其实也很间单,其实就是在对象里添加了一个子对象masterReferenc ...
- ASP.NET AJAX入门系列(11):在多个UpdatePanle中使用Timer控件
本文将使用Timer控件更新两个UpdatePanel控件,Timer控件将放在UpdatePanel控件的外面,并将它配置为UpdatePanel的触发器,翻译自官方文档. 主要内容 在多个Upda ...
- C# windows服务:C#windows服务中的Timer控件的使用
C# windows服务程序中的Timer控件的使用问题是如何解决的呢? 今天和同事一起研究了下C# windows服务程序中的Timer控件的使用的写法. 我们在建立一个C# windows服务程序 ...
- Boost中的Timer的使用——计算时间流逝
使用Boost中的Timer库计算程序的运行时间 程序开发人员都会面临一个共同的问题,即写出高质量的代码完毕特定的功能.评价代码质量的一个重要标准就是算法的运行效率,也就是算法的运行时间.为了可靠的提 ...
- Java中定时器Timer致命缺点(附学习方法)
简介 这篇文章我一直在纠结到底要不要写,不想写一来因为定时器用法比较简单,二来是面试中也不常问.后来还是决定写了主要是想把自己分析问题思路分享给大家,让大家在学习过程中能够参考,学习态度我相信大部分人 ...
随机推荐
- <runtime> 的 <assemblyIdentity> 元素和<bindingRedirect> 元素
1.<assemblyIdentity> 元素 包含关于该程序集的标识信息. <assemblyIdentity name="assembly name" pub ...
- 基于vue2.0的一个分页组件
分页组件在项目中经常要用到之前一直都是在网上找些jq的控件来用(逃..),最近几个项目用上vue了项目又刚好需要一个分页的功能.于是百度发现几篇文章介绍的实在方式有点复杂, 没耐心看自己动手造轮子写了 ...
- 整理js继承
实现继承的方法: 一,原型链:利用原型让一个引用类型继承另一个引用类型的属性和方法 function SuperType(){ this.property=true; } SuperType.prot ...
- <转>科普CPU Cache line
转载于http://coolshell.cn/articles/10249.html CPU cache一直是理解计算机体系架构的重要知识点,也是并发编程设计中的技术难点,而且相关参考资料如同过江之鲫 ...
- 检测delphi的程序的内存泄漏
在主窗体的FormCreate 加入ReportMemoryLeaksOnShutdown := True;
- 正三角形的外接圆面积,nyoj-274
正三角形的外接圆面积 时间限制:1000 ms | 内存限制:65535 KB 难度:0 描述给你正三角形的边长,pi=3.1415926 ,求正三角形的外接圆面积. 输入 只有一组测试数据 ...
- C语言的本质(22)——C标准库之字符串操作
编译器.浏览器.Office套件等程序的主要功能都是符号处理,符号处理功能在程序中占相当大的比例,无论多复杂的符号处理都是由各种基本的字符串操作组成的,下面介绍如何用C语言的库函数做字符串初始化.取长 ...
- 体验下Xcode5与ios7
IOS7的最新更新. 1.自主选择默认地图应用苹果在iOS 6中移除了谷歌地图,使用了自家研发的苹果地图.不得不说,这款自带的地图应用可以说烂到了一定的程度,自发布之后便问题不断.正因如此,苹果应该允 ...
- 启动Tomcat的几种方式
启动Tomcat有两种场景,一是部署时启动,二是开发时启动.部署时基本上是通过war包来启动,而开发时的启动方式多种多样,下面拟介绍几种适用于开发时启动Tomcat的方法. 在DOS命令行启动 Apa ...
- PHP单例模式编写
今天来点基础的设计模式: 如何利用单例模式实现一个数据库中间层 class Db{ static private $_instance; //当前数据库连接实例 static public funct ...