CodeZine(コードジン)

特集ページ一覧

POCO::Foundationでデザインパターン - マルチスレッド編 -

オープンソースC++用クラスライブラリPOCO活用講座(5)

  • LINEで送る
  • このエントリーをはてなブックマークに追加
2008/07/04 14:00
目次

POCOによるワーカースレッド(Worker Thread)・パターン

 スレッド関連クラスを応用して、ワーカースレッド・パターンのサンプルプログラムを作ってみました。POCOのソースと一緒に配布されるサンプルコードを土台として、若干の変更を加えました。

 ワーカースレッド・パターンの動きをざっと説明すると、次のようになります。

  1. まず複数のワーカースレッド(作業スレッド)を生成します。
  2. 各スレッドは、共有のリソースに対して「仕事」をとりにいきます。
  3. 仕事がある場合はその作業を行い、ない場合は新しい仕事が見つかるまで待機します。
  4. 共有のリソースに仕事を追加していきます。
  5. 順次ワーカースレッドが手分けして処理を行います。
  6. 仕事の追加を終えたら、すべての仕事が処理されるまで待機します。

サンプルコード

 まず最初にサンプルコードを紹介することにします。

ワーカースレッド・パターン サンプルコード
#include "Poco/Notification.h"
#include "Poco/NotificationQueue.h"
#include "Poco/ThreadPool.h"
#include "Poco/Thread.h"
#include "Poco/Runnable.h"
#include "Poco/Mutex.h"
#include "Poco/Random.h"

#include "Poco/AutoPtr.h"

#include <iostream>

// ワーカースレッドへの通知クラス
class WorkNotification: public Poco::Notification
{
  // 通知の番号
  int    _ix;

public:
  WorkNotification( int i ): _ix(i)
  {
  }

  // 保持している番号を返す
  int ix() const
  {
    return _ix;
  }

  // コマンド処理
  void execute()
  {
    // 乱数クラス
    Poco::Random  rnd;

    // 同じ乱数列とならないように
    rnd.seed();

    // 乱数でSleepする(0~199ミリ秒)
    Poco::Thread::sleep( rnd.next(200) );
  }
};

// ワーカースレッドクラス
// 通知キューから通知オブジェクトを取り出し、実行する。
class Worker: public Poco::Runnable
{
  // スレッド識別名
  std::string         _name;

  // 通知キュー
  Poco::NotificationQueue&  _queue;

  // 排他処理用Mutex
  static Poco::FastMutex    _mutex;

public:
  Worker(const std::string& name, Poco::NotificationQueue& queue):
    _name(name), _queue(queue)
  {
  }

  // スレッドのメイン処理
  void run()
  {
    for (;;) {
      // 通知キューからデータが取得できるまで待機
      Poco::AutoPtr<Poco::Notification> pNf(_queue.waitDequeueNotification());
      if (pNf) {
        WorkNotification* pWorkNf = dynamic_cast<WorkNotification*>(pNf.get());
        if (pWorkNf) {
          {
            Poco::FastMutex::ScopedLock lock(_mutex);
            std::cout << _name << " excute No." << pWorkNf->ix() << std::endl;
          }
          // コマンド実行
          pWorkNf->execute();
        }
      }
      else
        break;  // 返値がNULLのときはスレッドを終了
    }
  }
};
Poco::FastMutex Worker::_mutex; // static変数の実体

int _tmain(int argc, _TCHAR* argv[])
{
  // 通知オブジェクトのキュー
  Poco::NotificationQueue queue;

  // ワーカースレッドを作成
  Worker worker1( "Worker-1", queue );
  Worker worker2( "Worker-2", queue );
  Worker worker3( "Worker-3", queue );

  // スレッドプール
  Poco::ThreadPool pool;

  // 各ワーカースレッドの登録と開始
  pool.start( worker1 );
  pool.start( worker2 );
  pool.start( worker3 );

  // 通知オブジェクト50個をキューに積む
  for (int i = 0; i < 50; ++i) {
    queue.enqueueNotification( new WorkNotification( i ) );
                         // 順番を渡す
  }

  // キューが空になるまで、メインスレッドは待機。
  while ( !queue.empty() ) Poco::Thread::sleep(200);

  // すべてのワーカースレッドが処理待ちになるまでSleepしておく
  Poco::Thread::sleep(200);

  // 全ワーカースレッドへ終了指示
  queue.wakeUpAll();

  // 全ワーカースレッドの終了待機
  pool.joinAll();

  return 0;
}

 このサンプルコードに新たに登場するPOCOのクラスは次のとおりです。

その他のクラス
クラス名概要
Notification通知クラス
NotificationQueue通知クラス用キュー構造のコンテナクラス
Poco::Random乱数を生成するクラス

 POCOでは複数のスレッドを扱うためにPoco::ThreadPool(スレッドプール)というクラスが提供されています。スレッドの生成はそれなりのコストがかかる処理ですから、生成と廃棄を繰り返すことは効率的ではありません。そこでThreadPoolクラスでは、あらかじめスレッドを生成し、それをプールしておきます。必要に応じてプールしてあるスレッドを使いまわすことで、効率のよい複数スレッドの管理を実現できるようになっています。ちなみに、Javaや.NETのクラスライブラリにも、同じ名前で同様のクラスが存在します。

 前述の説明で用いた「仕事」という概念は、POCOではNotification(通知)という考え方で実装しています。ワーカースレッドに対して、メッセージなどを「通知」するということです。通知の受け渡しを実装したクラスとして、Poco::Notificationクラス、Poco::NotificationQueueクラスが用意されています。NotificationQueueクラスは、Notificationオブジェクトを保有するキュー構造のコンテナクラスです。

 サンプルコードでは単なる通知という役割だけでなく、「仕事」の具体的な処理も行わせるようにクラスを拡張しました。なお、このサンプルコードのように処理をオブジェクトとして捉えたパターンを、コマンドパターンと呼びます。

 POCOによるスレッドプールの概要を図にしてみました。

スレッドプール概要図
スレッドプール概要図

  • LINEで送る
  • このエントリーをはてなブックマークに追加

バックナンバー

連載:オープンソースC++用クラスライブラリPOCO活用講座

著者プロフィール

  • WINGSプロジェクト 高江 賢(タカエ ケン)

    <WINGSプロジェクトについて> 有限会社 WINGSプロジェクトが運営する、テクニカル執筆コミュニティ(代表 山田祥寛)。主にWeb開発分野の書籍/記事執筆、翻訳、講演等を幅広く手がける。2018年11月時点での登録メンバは55名で、現在も執筆メンバを募集中。興味のある方は、どしどし応募頂...

  • 山田 祥寛(ヤマダ ヨシヒロ)

    静岡県榛原町生まれ。一橋大学経済学部卒業後、NECにてシステム企画業務に携わるが、2003年4月に念願かなってフリーライターに転身。Microsoft MVP for ASP/ASP.NET。執筆コミュニティ「WINGSプロジェクト」代表。 主な著書に「入門シリーズ(サーバサイドAjax/XM...

あなたにオススメ

All contents copyright © 2005-2021 Shoeisha Co., Ltd. All rights reserved. ver.1.5