Poco::ActiveMethod

Poco::ActiveMethod は、Future Pattern を実現するためのものです。

要点を言えば、ある処理を別スレッドで起動し、起動元スレッドでは、その処理が終了するまで
(何か別のことでもしながら)待って、その処理結果を使うという感じです。

# ちなみに私は Future Pattern を「下請けに丸投げー納入チェックのみ」パターンと呼んでいます。

別スレッドでの処理に適当なものが思いつかなかったので、単純な整数の掛け算をやってみました。

ActiveMethodTest.cpp

#include <Poco/ActiveMethod.h>
#include <Poco/ActiveResult.h>
#include <Poco/Format.h>
#include <Poco/Random.h>
 
#include <deque>
 
#include "ScopedLogMessage.h"
#include "PrepareConsoleLogger.h"
 
class ActiveMultiplier;
 
struct MultiplierData
{
	int			threadID;
	ActiveMultiplier*	multiplier;
	int			callCount;
	std::pair<int, int>	source;
	int			result;
 
	MultiplierData()
	{
		threadID	= 0;
		multiplier	= NULL;
		callCount	= 0;
		source.first	= 0;
		source.second	= 0;
		result		= 0;
	}
};
 
class ActiveMultiplier
{
public:
	ActiveMultiplier() :
		multiply(this, &ActiveMultiplier::multiplyImpl)
	,	m_callCount(0)
	,	m_msg(" ActiveMultiplier ", "start", "end")
	{
	}
	Poco::ActiveMethod<MultiplierData, MultiplierData, ActiveMultiplier> multiply;
private:
	MultiplierData multiplyImpl(const MultiplierData& args)
	{
		ScopedLogMessage msg(" ActiveMultiplier::multiplyImpl ", "start", "end");
 
    	++m_callCount;
		msg.Message( Poco::format("  ActiveMultiplier::multiply(%d*%d) invoked from thread[%d] [callCount=%d]"
					,	args.source.first
					,	args.source.second
					,	args.threadID
					,	m_callCount) );
		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(ActiveMultiplier* multiplier, Poco::Random& random)
{
	MultiplierData data;
 
	Poco::Thread* p_thread = Poco::Thread::current();
	data.threadID		= (0 == p_thread) ? 0:p_thread->id();
	data.multiplier		= multiplier;
	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("ActiveMethodTest ", "start", "end");
 
	Poco::Random random;
 
	std::deque< Poco::ActiveResult<MultiplierData> > activeResults;
 
	const int kNumMutiplier = 2;
	for(int i=0; i<kNumMutiplier; ++i)
	{
		ActiveMultiplier* multiplier = new ActiveMultiplier;
		// Future pattern
		activeResults.push_back(multiplier->multiply(PrepareMultiplierData(multiplier, 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("  ActiveMultiplier::multiply(%d*%d) result=%d [callCount=%d]"
					,	result.data().source.first
					,	result.data().source.second
					,	result.data().result
					,	result.data().callCount)	);
		delete result.data().multiplier;
		activeResults.pop_front();
	}
 
	return 0;
}

Results of execution

・ActiveMultiplier のインスタンス毎に別のスレッドで掛け算。
・その隙に、メインスレッドで何か実行。
・メインスレッドで計算結果表示。

[0] ActiveMethodTest start
[0]  ActiveMultiplier start
[0]  ActiveMultiplier start
[1]  ActiveMultiplier::multiplyImpl start
[0]   doing something...
[2]  ActiveMultiplier::multiplyImpl start
[1]   ActiveMultiplier::multiply(9*4) invoked from thread[0] [callCount=1]
[1]  ActiveMultiplier::multiplyImpl end
[0]   ActiveMultiplier::multiply(9*4) result=36 [callCount=1]
[2]   ActiveMultiplier::multiply(6*3) invoked from thread[0] [callCount=1]
[0]  ActiveMultiplier end
[2]  ActiveMultiplier::multiplyImpl end
[0]   ActiveMultiplier::multiply(6*3) result=18 [callCount=1]
[0]  ActiveMultiplier end
[0] ActiveMethodTest end

Downloads

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

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>