Poco::ThreadLocal

Poco::ThreadLocal を紹介します。

このクラスは、スレッドローカル変数を宣言するのに使います。基本的にはスマートポインタクラスに似ていますが、スレッド毎に異なるオブジェクトを参照します。オブジェクトは、初めて参照された時に生成されます。各スレッドは、自分自身のローカルデータだけを参照することができ、他スレッドのローカルデータを参照することはできません。

以前紹介した Poco::NestedDiagnosticContext は、内部でこの Poco::ThreadLocal を使っています。

ThreadLocalTest.cpp

・3つのスレッドを作り、それぞれで(Linux 等での)コマンドヒストリーもどきを作ってチェック。
・kCommands[] にあるコマンドの中から、Poco::ThreadLocal で宣言した Poco::Random を使って
 ランダムなものを選び、Poco::ThreadLocal で宣言した std::vector に追加し、最終結果を m_History
 にコピー。
・history() を呼んで、コマンドヒストリーもどきを表示。

#include <Poco/Runnable.h>
#include <Poco/Random.h>
#include <Poco/Thread.h>
#include <Poco/Format.h>
#include <Poco/ThreadLocal.h>
 
#include <string>
#include <vector>
 
#include "ScopedLogMessage.h"
#include "PrepareConsoleLogger.h"
 
const std::string kCommands[] = {	"ls -la"
				,	"date"
				,	"uname -a"
				,	"ps -ax"
				,	"pwd"
				,	"who am i"
				,	"users"
				,	"groups"
				,	"uptime"
				,	"svn update"
				};
 
const std::size_t kNumCommands = sizeof(kCommands)/sizeof(kCommands[0]);
 
class TestThreadLocal: public Poco::Runnable
{
public:
	TestThreadLocal()
	{
	}
 
	void run()
	{
		m_pRandom->seed(3 * Poco::Thread::current()->id());
 
		// simulate executing commands a few times
		std::size_t numCommands = m_pRandom->next(kNumCommands);
		for(std::size_t i=0; i<numCommands; ++i)
		{
			std::string str(kCommands[m_pRandom->next(kNumCommands)]);
			m_pHistory->push_back(str);
		}
		m_History = *m_pHistory;
	}
 
	std::string history()
	{
		std::string str;
 
		std::vector<std::string>::iterator itr = m_History.begin();
		std::vector<std::string>::iterator itrEnd = m_History.end();
		while(itr != itrEnd)
		{
			str += "\n       " + *itr;
			++itr;
		}
		return str;
	}
 
private:
	static Poco::ThreadLocal< Poco::Random >		m_pRandom;
	static Poco::ThreadLocal< std::vector<std::string> >	m_pHistory;
	std::vector<std::string>				m_History;
};
 
Poco::ThreadLocal< Poco::Random	>		TestThreadLocal::m_pRandom;
Poco::ThreadLocal< std::vector<std::string> >	TestThreadLocal::m_pHistory;
 
int main(int /*argc*/, char** /*argv*/)
{
	PrepareConsoleLogger logger(Poco::Logger::ROOT, Poco::Message::PRIO_INFORMATION);
 
	ScopedLogMessage msg("ThreadLocalTest ", "start", "end");
 
	TestThreadLocal ttl1;
	TestThreadLocal ttl2;
	TestThreadLocal ttl3;
	Poco::Thread t1;
	Poco::Thread t2;
	Poco::Thread t3;
	t1.start(ttl1);
	t2.start(ttl2);
	t3.start(ttl3);
	t1.join();
	t2.join();
	t3.join();
	msg.Message(Poco::format(" TestThreadLocal #1\n      history():%s", ttl1.history()));
	msg.Message(Poco::format(" TestThreadLocal #2\n      history():%s", ttl2.history()));
	msg.Message(Poco::format(" TestThreadLocal #3\n      history():%s", ttl3.history()));
 
	return 0;
}

Results of execution

[0] ThreadLocalTest start
[0]  TestThreadLocal #1
      history():
       groups
       uptime
[0]  TestThreadLocal #2
      history():
       date
       groups
       users
       uname -a
       svn update
[0]  TestThreadLocal #3
      history():
       svn update
       date
       pwd
[0] ThreadLocalTest end

Downloads

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

Subversion

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

Reference

http://pocoproject.org にある Threads のプレセンテーション。(PDF)

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>