POCO C++库学习和分析 -- 线程 (三)

POCO C++库学习和分析 -- 线程 (三)

4. 定时器

定时器作为线程的扩展,也是编程时经常会被用到的元素。在程序设计上,定时器的作用是很简单。预定某个定时器,即希望在未来的某个时刻,程序能够得到时间到达的触发信号。

编程时,一般对定时器使用有下面一些关注点:

1. 定时器的精度。Poco中的定时器精度并不是很高,具体精度依赖于实现的平台(Windows or Linux)

2. 定时器是否可重复,即定时器是否可触发多次。 Poco中的定时器精度支持多次触发也支持一次触发,由其构造函数Timer决定

	Timer(long startInterval = 0, long periodicInterval = 0);
		/// Creates a new timer object. StartInterval and periodicInterval
		/// are given in milliseconds. If a periodicInterval of zero is 
		/// specified, the callback will only be called once, after the
		/// startInterval expires.
		/// To start the timer, call the Start() method.

3. 一个定时器是否可以设置多个时间。 Poco中定时器不支持设置多个时间,每个定时器对应一个时间。如果需要多个时间约定的话,使用者要构造多个定时器。


4.1 定时器实现

Poco中的定时器并不复杂,下面是它的类图。


在类图中,Timer继承自Runnable类,也就是说Timer实现了自己的run函数。来看一看,run函数的实现。

void Timer::run()
{
	Poco::Timestamp now;
	long interval(0);
	do
	{
		long sleep(0);
		do
		{
			now.update();
			sleep = static_cast<long>((_nextInvocation - now)/1000);
			if (sleep < 0)
			{
				if (interval == 0)
				{
					sleep = 0;
					break;
				}
				_nextInvocation += interval*1000;
				++_skipped;
			}
		}
		while (sleep < 0);

		if (_wakeUp.tryWait(sleep))
		{
			Poco::FastMutex::ScopedLock lock(_mutex);
			_nextInvocation.update();
			interval = _periodicInterval;
		}
		else
		{
			try
			{
				_pCallback->invoke(*this);
			}
			catch (Poco::Exception& exc)
			{
				Poco::ErrorHandler::handle(exc);
			}
			catch (std::exception& exc)
			{
				Poco::ErrorHandler::handle(exc);
			}
			catch (...)
			{
				Poco::ErrorHandler::handle();
			}
			interval = _periodicInterval;
		}
		_nextInvocation += interval*1000;
		_skipped = 0;
	}
	while (interval > 0);
	_done.set();
}
在run函数中,我们发现定时器的业务就是不断更新下一次触发时间,并通过睡眠等待到预定时间,触发调用者业务。


4.2 定时器使用

最后让我们来看一个定时器的例子:

#include "Poco/Timer.h"
#include "Poco/Thread.h"
using Poco::Timer;
using Poco::TimerCallback;

class TimerExample
{
	public:
	void onTimer(Poco::Timer& timer)
	{
		std::cout << "onTimer called." << std::endl;
	}
};

int main(int argc, char** argv)
{
	TimerExample te;
	Timer timer(250, 500); // fire after 250ms, repeat every 500ms
	timer.start(TimerCallback<TimerExample>(te, &TimerExample::onTimer));
	Thread::sleep(5000);
	timer.stop();
	return 0;
}



(版权所有,转载时请注明作者和出处 http://blog.csdn.net/arau_sh/article/details/8615257



posted @ 2013-02-26 21:09  在天与地之间  阅读(1027)  评论(0编辑  收藏  举报