Poco::RWLock を紹介します。
Poco::RWLock を使うと、複数の同時動作可能な reader もしくは唯一の排他的な writer を実現できます。
RWLockTest.cpp
・スレッドを5つ立て、それぞれで同一のカウンタを複数回 read/write し、カウンタの最終値に矛盾が
無いことを確認し、処理時間も計測。
・Poco::RWLock::readLock() や Poco::RWLock::writeLock() と Poco::RWLock::unlock() の組み合わせでも
もちろん動作するが、RAII イディオムを使った
Poco::ScopedReadRWLock()
Poco::ScopedWriteRWLock()
を利用。
#include <Poco/Format.h> #include <Poco/Runnable.h> #include <Poco/Thread.h> #include <Poco/RWLock.h> #include <Poco/Stopwatch.h> #include <string> #include "ScopedLogMessage.h" #include "PrepareConsoleLogger.h" const int kNumLoops = 1000; const int kNumRunnable = 5; class RWLockRunnable: public Poco::Runnable { public: RWLockRunnable(Poco::RWLock& lock, volatile int& counter) : m_Lock(lock) , m_Counter(counter) , m_Ok(true) { } void run() { int lastCount = 0; for(int i=0; i<kNumLoops; ++i) { { // scope for read lock Poco::ScopedReadRWLock lock(m_Lock); lastCount = m_Counter; for(int k=0; k<100; ++k) { if(m_Counter != lastCount) { m_Ok = false; } Poco::Thread::yield(); } } { // scope for write lock Poco::ScopedWriteRWLock lock(m_Lock); for(int k=0; k<100; ++k) { --m_Counter; Poco::Thread::yield(); } for(int k=0; k<100; ++k) { ++m_Counter; Poco::Thread::yield(); } ++m_Counter; if(m_Counter <= lastCount) { m_Ok = false; } } } } bool ok() const { return m_Ok; } private: Poco::RWLock& m_Lock; volatile int& m_Counter; bool m_Ok; }; int main(int /*argc*/, char** /*argv*/) { PrepareConsoleLogger logger(Poco::Logger::ROOT, Poco::Message::PRIO_INFORMATION); ScopedLogMessage msg("RWLockTest ", "start", "end"); Poco::Stopwatch stopwatch; stopwatch.start(); Poco::RWLock lock; int counter = 0; RWLockRunnable* pRunnable[kNumRunnable]; Poco::Thread thread[kNumRunnable]; for(int i=0; i<kNumRunnable; ++i) { pRunnable[i] = new RWLockRunnable(lock, counter); thread[i].start(*pRunnable[i]); } for(int i=0; i<kNumRunnable; ++i) { thread[i].join(); if(!pRunnable[i]->ok()) { msg.Message(Poco::format(" RWLockRunnable[%i] failed!", i)); } delete pRunnable[i]; } stopwatch.stop(); msg.Message(Poco::format(" counter = %i (expected: %i)", counter, kNumLoops*kNumRunnable)); msg.Message(Poco::format(" Elapsed time = %.3fmSec", (1000.0 * stopwatch.elapsed()) / stopwatch.resolution())); return 0; } |
Results of execution
[0] RWLockTest start [0] counter = 5000 (expected: 5000) [0] Elapsed time = 1431.262mSec [0] RWLockTest end |
Downloads
・ここをクリックすると、makefile や VC++ プロジェクトなど一式がダウンロードできます。
(2013.05.31 updated)
・2010年7月29日からのダウンロード数:1086
Subversion
・フリーの Subversion ホスティングサービス Assemblaで、ソースコードを管理しています。
Reference
・http://pocoproject.org にある Threads のプレセンテーション。(PDF)
![]() |
Copyright © 2010 Round Square Inc. All rights reserved. |
---|
0 Comments.