Poco::TimedNotificationQueue を紹介します。
子スレッドから時刻指定の Notification を enqueue し、メインスレッドで dequeue するサンプルです。
TimedNotificationQueueTest.cpp
・3つの Child スレッドから、それぞれ現在時刻+α(最大 500msec)の時刻指定で Notification を
3つずつ enqueue する。
・enqueue する時に、指定時刻を表示。
・時刻は UTC を渡す(つまり、Loacl 時刻ではない)ことに注意。
・Poco::TimedNotificationQueue の場合、dequeue するのは1つだけ(つまり複数スレッドで dequeue
してはいけない)という制約があるので、ここでは Main スレッドで dequeue。
(前回の Worker Thread パターンとは主従が逆)
・dequeue する時に、指定時刻を表示。
#include <Poco/Format.h> #include <Poco/Notification.h> #include <Poco/TimedNotificationQueue.h> #include <Poco/AtomicCounter.h> #include <Poco/DateTime.h> #include <Poco/Timespan.h> #include <Poco/ThreadPool.h> #include <Poco/Thread.h> #include <Poco/Runnable.h> #include <Poco/AutoPtr.h> #include <Poco/Random.h> #include <Poco/DateTimeFormatter.h> #include <Poco/Timezone.h> #include <string> #include "ScopedLogMessage.h" #include "PrepareConsoleLogger.h" const int kNumEnqueueByChild = 3; const long kSleepTime = 200; const long kScheduleMaxTime = 500; class ChildNotification : public Poco::Notification { public: ChildNotification(int data, const std::string& name, const Poco::DateTime& datetime): m_data(data) , m_name(name) , m_datetime(datetime) { m_datetime.makeLocal(Poco::Timezone::tzd()); } int data() const { return m_data; } std::string name() const { return m_name; } std::string datetime() const { return Poco::DateTimeFormatter::format(m_datetime.timestamp(), "%H:%M:%S.%i"); } private: int m_data; const std::string m_name; Poco::DateTime m_datetime; }; class Child : public Poco::Runnable { public: typedef Poco::AutoPtr<ChildNotification> ChildNotificationPtr; Child(const std::string& name, Poco::TimedNotificationQueue& queue, ScopedLogMessage& msg): m_name(name) , m_queue(queue) , m_msg(msg) { m_msg.Message(Poco::format(" %s created", m_name)); } ~Child() { m_msg.Message(Poco::format(" %s deleted", m_name)); } void run() { for(int i=0; i<kNumEnqueueByChild; ++i) { int counter = ++m_counter; Poco::DateTime datetime; datetime += Poco::Timespan(m_rnd.next(kScheduleMaxTime)*1000); m_queue.enqueueNotification(new ChildNotification(counter, m_name, datetime), datetime.timestamp()); datetime.makeLocal(Poco::Timezone::tzd()); m_msg.Message(Poco::format(" enqueueNotification #%d from %s (%s)" , counter , m_name , Poco::DateTimeFormatter::format(datetime.timestamp(), "%H:%M:%S.%i"))); } } static int NumEnqueued(void) { return m_counter; } private: std::string m_name; Poco::TimedNotificationQueue& m_queue; ScopedLogMessage& m_msg; static Poco::AtomicCounter m_counter; static Poco::Random m_rnd; }; Poco::AtomicCounter Child::m_counter(0); Poco::Random Child::m_rnd; int main(int /*argc*/, char** /*argv*/) { PrepareConsoleLogger logger(Poco::Logger::ROOT, Poco::Message::PRIO_INFORMATION); ScopedLogMessage msg("TimedNotificationQueueTest ", "start", "end"); Poco::TimedNotificationQueue queue; Child child1("Child 1", queue, msg); Child child2("Child 2", queue, msg); Child child3("Child 3", queue, msg); Poco::ThreadPool::defaultPool().start(child1); Poco::ThreadPool::defaultPool().start(child2); Poco::ThreadPool::defaultPool().start(child3); int numDequeued = 0; while(numDequeued < Child::NumEnqueued()) { Poco::Notification::Ptr pNf(queue.waitDequeueNotification()); if(pNf) { Child::ChildNotificationPtr pChildNf = pNf.cast<ChildNotification>(); if(pChildNf) { msg.Message(Poco::format(" got child notification #%d from %s (%s)" , pChildNf->data() , pChildNf->name() , pChildNf->datetime())); ++numDequeued; Poco::Thread::sleep(kSleepTime); } } else break; } return 0; } |
Results of execution
・Poco::TimedNotificationQueue の場合は、queue に積んだ順ではなく、指定した Timestamp の
若い順に処理される。
[0] TimedNotificationQueueTest start [0] Child 1 created [0] Child 2 created [0] Child 3 created [1] enqueueNotification #1 from Child 1 (05:17:15.460) [2] enqueueNotification #2 from Child 2 (05:17:15.528) [3] enqueueNotification #3 from Child 3 (05:17:15.449) [1] enqueueNotification #4 from Child 1 (05:17:15.573) [2] enqueueNotification #5 from Child 2 (05:17:15.374) [3] enqueueNotification #6 from Child 3 (05:17:15.162) [1] enqueueNotification #7 from Child 1 (05:17:15.277) [2] enqueueNotification #8 from Child 2 (05:17:15.212) [3] enqueueNotification #9 from Child 3 (05:17:15.555) [0] got child notification #6 from Child 3 (05:17:15.162) [0] got child notification #8 from Child 2 (05:17:15.212) [0] got child notification #7 from Child 1 (05:17:15.277) [0] got child notification #5 from Child 2 (05:17:15.374) [0] got child notification #3 from Child 3 (05:17:15.449) [0] got child notification #1 from Child 1 (05:17:15.460) [0] got child notification #2 from Child 2 (05:17:15.528) [0] got child notification #9 from Child 3 (05:17:15.555) [0] got child notification #4 from Child 1 (05:17:15.573) [0] Child 3 deleted [0] Child 2 deleted [0] Child 1 deleted [0] TimedNotificationQueueTest end |
Downloads
・ここをクリックすると、makefile や VC++ プロジェクトなど一式がダウンロードできます。
(2013.05.31 updated)
・2010年6月10日からのダウンロード数:1120
Subversion
・フリーの Subversion ホスティングサービス Assemblaで、ソースコードを管理しています。
![]() |
Copyright © 2010 Round Square Inc. All rights reserved. |
---|
0 Comments.