Poco::Util::Timer

Poco::Util::TimerTask オブジェクトをバックグランドで実行するためにスケジューリングする Poco::Util::Timer を紹介します。

Poco::Util::Timer は、スケジューリングされたタスクを1つのスレッドで順番に処理するので、それぞれのタスクの処理は速やかに終わるようにしないと、それに続くタスクの処理が遅れてしまいます。

スケジューリングには次の3つの方法があります:

Method Description
schedule(TimerTask::Ptr pTask, Poco::Timestamp time) 時刻指定の単発
schedule(TimerTask::Ptr pTask, long delay, long interval)
schedule(TimerTask::Ptr pTask, lPoco::Timestamp time, long interval)
初回ディレイ指定または時刻指定で繰り返し
繰り返しは、タスクの終了時基準
scheduleAtFixedRate(TimerTask::Ptr pTask, long delay, long interval)
scheduleAtFixedRate(TimerTask::Ptr pTask, lPoco::Timestamp time, long interval)
初回ディレイ指定または時刻指定で繰り返し
繰り返しは、タスクの開始時基準

スレッドセーフになっているので、複数のスレッドから Poco::Util::Timer にタスクをスケジューリングしても大丈夫です。

UtilTimerTest.cpp

・MyTimerTask::onTimer 内に 100msec のディレイを入れ、イベントを投げる。
・TestSchedule() では、500msec 後に MyTimerTask::onTimer が一度だけ呼ばれるように
 スケジューリングし、イベント待ち。
・TestFixedRate() では、500msec 後から MyTimerTask::onTimer が 500msec 毎に呼ばれるように
 scheduleAtFixedRate でスケジューリングし、イベント待ち。
・TestFixedRate() では、500msec 後から MyTimerTask::onTimer が 500msec 毎に呼ばれるように
 schedule でスケジューリングし、イベント待ち。

#include <Poco/Util/Timer.h>
#include <Poco/Util/TimerTask.h>
#include <Poco/Util/TimerTaskAdapter.h>
#include <Poco/Event.h>
#include <Poco/Timestamp.h>
#include <Poco/Format.h>
 
#include <string>
 
#include "ScopedLogMessage.h"
#include "PrepareConsoleLogger.h"
 
class MyTimerTask
{
public:
	MyTimerTask(ScopedLogMessage& msg, Poco::Event& event) :
		m_msg(msg)
	,	m_event(event)
	{
	}
	void onTimer(Poco::Util::TimerTask& task)
	{
		m_msg.Message("  MyTimerTask::onTimer() called");
		Poco::Thread::sleep(100);	// 100msec
		m_event.set();
	}
private:
	ScopedLogMessage&	m_msg;
	Poco::Event&		m_event;
};
 
void TestSchedule(ScopedLogMessage& msg, Poco::Util::Timer& timer)
{
	msg.Message("--- schedule ---");
 
	const Poco::Timestamp::TimeDiff kTimeDiff = 500000;	// 500msec
 
	Poco::Event event;
	MyTimerTask task(msg, event);
	Poco::Util::TimerTask::Ptr pTask = new Poco::Util::TimerTaskAdapter<MyTimerTask>(task, &MyTimerTask::onTimer);
 
	Poco::Timestamp time;
	time += kTimeDiff;
	timer.schedule(pTask, time);
 
	event.wait();
	msg.Message(Poco::format("    execution delay from scheduled: %Ldusec"
				, pTask->lastExecution().epochMicroseconds()-time.epochMicroseconds()));
}
 
Poco::Timestamp::TimeVal WaitAndShowTime(	ScopedLogMessage& msg
					,	Poco::Event& event
					,	Poco::Util::TimerTask::Ptr& pTask
					,	const std::string& text
					,	Poco::Timestamp::TimeVal refTime)
{
	event.wait();
	Poco::Timestamp::TimeVal val = pTask->lastExecution().epochMicroseconds();
	msg.Message(Poco::format("%s %7.3fmsec", text, 0.001*(val-refTime)));
	return val;
}
 
void TestFixedRate(ScopedLogMessage& msg, Poco::Util::Timer& timer)
{
	msg.Message("--- schedule fixed rate ---");
 
	Poco::Event event;
	MyTimerTask task(msg, event);
	Poco::Util::TimerTask::Ptr pTask = new Poco::Util::TimerTaskAdapter<MyTimerTask>(task, &MyTimerTask::onTimer);
 
	Poco::Timestamp time;
	timer.scheduleAtFixedRate(pTask, 500, 500);	// 500msec
 
	Poco::Timestamp::TimeVal val;
	val = WaitAndShowTime(msg, event, pTask, "    delay   :", time.epochMicroseconds());
	for(int i=0; i<2; ++i)
	{
		val = WaitAndShowTime(msg, event, pTask, "    interval:", val);
	}
	pTask->cancel();
}
 
void TestInterval(ScopedLogMessage& msg, Poco::Util::Timer& timer)
{
	msg.Message("--- schedule interval ---");
 
	Poco::Event event;
	MyTimerTask task(msg, event);
	Poco::Util::TimerTask::Ptr pTask = new Poco::Util::TimerTaskAdapter<MyTimerTask>(task, &MyTimerTask::onTimer);
 
	Poco::Timestamp time;
	timer.schedule(pTask, 500, 500);	// 500msec
 
	Poco::Timestamp::TimeVal val;
	val = WaitAndShowTime(msg, event, pTask, "    delay   :", time.epochMicroseconds());
	for(int i=0; i<2; ++i)
	{
		val = WaitAndShowTime(msg, event, pTask, "    interval:", val);
	}
	pTask->cancel();
}
 
int main(int /*argc*/, char** /*argv*/)
{
	PrepareConsoleLogger logger(Poco::Logger::ROOT, Poco::Message::PRIO_INFORMATION);
 
	ScopedLogMessage msg("UtilTimerTest ", "start", "end");
 
	Poco::Util::Timer timer;
 
	TestSchedule(msg, timer);
	TestFixedRate(msg, timer);
	TestInterval(msg, timer);
 
	return 0;
}

Results of execution

・TestFixedRate() では、interval が 500msec
・TestInterval() では、interval が 600msec (500msec + 100msec)
・MyTimerTask 側は thread ID が 1

[0] UtilTimerTest start
[0] --- schedule ---
[1]   MyTimerTask::onTimer() called
[0]     execution delay from scheduled: 259usec
[0] --- schedule fixed rate ---
[1]   MyTimerTask::onTimer() called
[0]     delay   : 500.117msec
[1]   MyTimerTask::onTimer() called
[0]     interval: 500.236msec
[1]   MyTimerTask::onTimer() called
[0]     interval: 500.253msec
[0] --- schedule interval ---
[1]   MyTimerTask::onTimer() called
[0]     delay   : 500.170msec
[1]   MyTimerTask::onTimer() called
[0]     interval: 600.252msec
[1]   MyTimerTask::onTimer() called
[0]     interval: 600.240msec
[0] UtilTimerTest end

Downloads

ここをクリックすると、makefile や VC++ プロジェクトなど一式がダウンロードできます。
(2013.05.31 updated)
・2010年5月29日からのダウンロード数:828

Subversion

・フリーの Subversion ホスティングサービス Assemblaで、ソースコードを管理しています。

Powered by POCO Copyright © 2010 Round Square Inc. All rights reserved.


Leave a Comment


NOTE - You can use these HTML tags and attributes:
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>