Poco::ActiveDispatcher

Poco::ActiveDispatcher は、Poco::ActiveMethod と似ていますが、処理が厳密にシリアライズされるところが異なります。

つまり、処理指示がキューに積まれ、そのキューから引き出されたものが順番に処理されます。
処理順が保証されるので、例えばハードウエアのアクセスルーチンや通信などに使えるのではないかと思います。

デザインパターンで言うと、Single Threaded Execution パターンになります。

ここでは、前回と同じく、別スレッドでの処理に単純な整数の掛け算をやっています。

ActiveDispatcherTest.cpp

#include <Poco/ActiveMethod.h>
#include <Poco/ActiveDispatcher.h>
#include <Poco/ActiveResult.h>
#include <Poco/Format.h>
#include <Poco/Random.h>
 
#include <deque>
 
#include "ScopedLogMessage.h"
#include "PrepareConsoleLogger.h"
 
struct MultiplierData
{
	int			threadID;
	int			callCount;
	std::pair<int, int>	source;
	int			result;
 
	MultiplierData()
	{
		threadID	= 0;
		callCount	= 0;
		source.first	= 0;
		source.second	= 0;
		result		= 0;
	}
};
 
class ActiveMultiplierDispatcher : public Poco::ActiveDispatcher
{
public:
	ActiveMultiplierDispatcher() :
		multiply(this, &ActiveMultiplierDispatcher::multiplyImpl)
	,	m_callCount(0)
 	,	m_msg(" ActiveMultiplierDispatcher ", "start", "end")
	{
	}
 
	Poco::ActiveMethod<MultiplierData, MultiplierData,
						ActiveMultiplierDispatcher, Poco::ActiveStarter<Poco::ActiveDispatcher> > multiply;
 
protected:
	// Single Threaded Execution pattern
	MultiplierData multiplyImpl(const MultiplierData& args)
	{
		ScopedLogMessage msg(" ActiveMultiplierDispatcher::multiplyImpl ", "start", "end");
 
		++m_callCount;
		msg.Message(	Poco::format("  ActiveMultiplierDispatcher::multiply(%d*%d) invoked from thread[%d] [callCount=%d]"
					,	args.source.first
					,	args.source.second
					,	args.threadID
					,	m_callCount)	);
 
		// simulate time consuming job
		Poco::Thread::sleep(500);	// 500mSec
 
		MultiplierData rtn = args;
		rtn.callCount = m_callCount;
		rtn.result = args.source.first * args.source.second;
 
		return rtn;
	}
 
	int			m_callCount;
	ScopedLogMessage	m_msg;
};
 
MultiplierData PrepareMultiplierData(Poco::Random& random)
{
	MultiplierData data;
 
	Poco::Thread* p_thread = Poco::Thread::current();
	data.threadID		= (0 == p_thread) ? 0:p_thread->id();
	data.source.first	= std::abs(random.nextChar() % 10);
	data.source.second	= std::abs(random.nextChar() % 10);
	return data;
}
 
int main(int /*argc*/, char** /*argv*/)
{
	PrepareConsoleLogger logger(Poco::Logger::ROOT, Poco::Message::PRIO_INFORMATION);
 
	ScopedLogMessage msg("ActiveDispatcherTest ", "start", "end");
 
	Poco::Random random;
 
	std::deque< Poco::ActiveResult<MultiplierData> > activeResults;
 
	ActiveMultiplierDispatcher multiplier;
 
	const int kNumMutiplier = 2;
	for(int i=0; i<kNumMutiplier; ++i)
	{
		// Future pattern
		activeResults.push_back(multiplier.multiply(PrepareMultiplierData(random)));
	}
 
	// some other task can be done here
	msg.Message("  doing something...");
 
	while(0 != activeResults.size())
	{
		Poco::ActiveResult<MultiplierData>& result = activeResults.front();
		result.wait();
		msg.Message(	Poco::format("  ActiveMultiplierDispatcher::multiply(%d*%d) result=%d [callCount=%d]"
					,	result.data().source.first
					,	result.data().source.second
					,	result.data().result
					,	result.data().callCount)	);
		activeResults.pop_front();
	}
 
	return 0;
}

Results of execution

・ActiveMultiplierDispatcher のインスタンスに掛け算を2回指示。
・別のスレッドで指示順に掛け算実行。
・その隙に、メインスレッドで何か実行。
・メインスレッドで計算結果表示。

[0] ActiveDispatcherTest start
[0]  ActiveMultiplierDispatcher start
[0]   doing something...
[1]  ActiveMultiplierDispatcher::multiplyImpl start
[1]   ActiveMultiplierDispatcher::multiply(7*7) invoked from thread[0] [callCount=1]
[1]  ActiveMultiplierDispatcher::multiplyImpl end
[1]  ActiveMultiplierDispatcher::multiplyImpl start
[0]   ActiveMultiplierDispatcher::multiply(7*7) result=49 [callCount=1]
[1]   ActiveMultiplierDispatcher::multiply(4*6) invoked from thread[0] [callCount=2]
[1]  ActiveMultiplierDispatcher::multiplyImpl end
[0]   ActiveMultiplierDispatcher::multiply(4*6) result=24 [callCount=2]
[0]  ActiveMultiplierDispatcher end
[0] ActiveDispatcherTest end

Downloads

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

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>