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致命缺点(附学习方法)
简介 这篇文章我一直在纠结到底要不要写,不想写一来因为定时器用法比较简单,二来是面试中也不常问.后来还是决定写了主要是想把自己分析问题思路分享给大家,让大家在学习过程中能够参考,学习态度我相信大部分人 ...
随机推荐
- PlSql复制角色、权限和添加角色权限
一.登录你想要复制数据库的用户
- 查询DB中每个表占用的空间大小
使用如下sql script可以获得每个数据库表所占用的空间大小,单位是KB create table #Data(name varchar(100),row varchar(100),reserve ...
- struts1:Struts配置文件初解
struts-config.xml是Struts的核心文件.该文件可配置各种组件,包括,FormBeans,Actions,ActionMappings,全局转发GlobalForwards,数据源D ...
- 从汇编看c++中指向成员变量的指针(二)
在从汇编看c++中指向成员变量的指针(一)中讨论的情形没有虚拟继承,下面来看看,当加入了虚拟继承的时候,指向成员变量的指针有什么变化. 下面是c++源码: #include <iostream& ...
- PHP扩展开发之简单类开发
接下来我们要用扩展的形式实现以下类(演示环境:linux.php-5.5.34-src) <?php class Person { private $_name; public function ...
- Samba服务器
Windows操作系统下:DOC命令下:netstat -an查看端口 (一)简介 文件服务器 (二)端口 smbd: 为clinet提高资源访问 tcp 139 445 (类似于windo ...
- atoi atol strtod strtol strtoul _gcvt
如果以下函数,您在使用的时候,总是输出一个莫名的值,是因为您忘记了引用头文件 #include <stdlib.h> 1- atoi int atoi(const char *nptr); ...
- 在Windows XP下手动安装Apache+MySQL+PHP环境 要点
在整个wamp环境搭建中,本质的工作如下: 1,配置系统对php中dll文件能默认处于调用状态.在windos下,对dll文件系统默认处于调用状态的,有两种采用的方式.第一种是:把需要调用dll文件复 ...
- you can Solve a Geometry Problem too(hdoj1086)
Problem Description Many geometry(几何)problems were designed in the ACM/ICPC. And now, I also prepare ...
- autofac使用笔记
在之前的项目中用来解耦的使用的轻型IOC框架是unity,它的使用也是很方便的提供在之前的文章的也提到过它的使用方式,但是使用久了之后发现了它的不足之处就是需要配置xml文件来对应的接口和实现的关系. ...