Physics-Station phst.hateblo.jp

旧 http://physics-station.blogspot.jp/ から当はてなブログに移行しました。間違ってるところがあればコメントください。記述の正確性は保証しません。

Pocoで複数のPoco::Threadを管理してみる

筆者は世に出すサンプルコードのことを甘く見ているので、こんなコードではダメだということに気づかれた方は、お手数でもコメントにお書きください。よろしくお願いいたします。

Visual Studio 2013 は中途半端にC++11が実装されており、スレッドまわりの全ての機能を使うことができない。 そこで、 Poco::Thread を使おうと考えた。

今回は、stlstd::vector で複数のPoco::Threadを管理する。例えば、Poco::Thread を複数作ることを許容し、その上限数を管理しする場合に使える。

#include <iostream>
#include <vector>

#include <Poco/Thread.h>
#include <Poco/Runnable.h>
#include <Poco/ErrorHandler.h>

class HeavyWorker : public Poco::Runnable
{
public:
    int i;
private:
    void run()
    {
        Sleep(1000);
        std::cout << "おわった id=" << i << std::endl;
        //throw std::exception();
    }
};

//例外クラス
class MyHandler : public Poco::ErrorHandler {

public:
    virtual void exception(const Poco::Exception& exc) {
        std::cout << "Poco Exception: " << exc.displayText() << std::endl;
    }
    virtual void exception(const std::exception& exc) {
        std::cout << "std::exception: " << exc.what() << std::endl;
    }
    virtual void exception() {
        std::cout << "Other exception" << std::endl;
    }
};

int main() {
    MyHandler handler;
    Poco::ErrorHandler::set(&handler);


    // スレッド管理用のベクタ
    std::vector<Poco::Thread*> vthread;
    // ワーカー管理用のベクタ
    std::vector<HeavyWorker*> vworker;
    int maxNumThread = 4;

    for (int i = 0; i < 20; i++) {

        while (true) {
            if (vthread.size() < maxNumThread) { break; }
            for (int i = 0; i < vthread.size(); i++) {
                if (vthread[i]->tryJoin(1)) {
                    delete vworker[i];
                    vworker.erase(vworker.begin() + i);
                    delete vthread[i];
                    vthread.erase(vthread.begin() + i);
                    i--;
                }
            }
        }
        std::cout << "現在のスレッド数" << vthread.size() << std::endl;

        Poco::Thread *thread = new Poco::Thread();
        HeavyWorker *worker = new HeavyWorker();
        worker->i = i;
        vworker.emplace_back(worker);
        thread->start(*worker);
        vthread.emplace_back(thread);
        Sleep(100);
    }
    for (int i = 0; i < vthread.size(); i++) {
        vthread[i]->join();
        delete vworker[i];
        vworker.erase(vworker.begin() + i);
        delete vthread[i];
        vthread.erase(vthread.begin() + i);
        i--;
        std::cout << "現在のスレッド数" << vthread.size() << std::endl;
    }
    //std::cin.get();
    return 0;
}

出力例

現在のスレッド数0
現在のスレッド数1
現在のスレッド数2
現在のスレッド数3
おわった id=0
現在のスレッド数3
おわった id=1
現在のスレッド数3
おわった id=2
現在のスレッド数3
おわった id=3
現在のスレッド数3
おわった id=4
現在のスレッド数3
おわった id=5
現在のスレッド数3
おわった id=6
現在のスレッド数3
おわった id=7
現在のスレッド数3
おわった id=8
現在のスレッド数3
おわった id=9
現在のスレッド数3
おわった id=10
現在のスレッド数3
おわった id=11
現在のスレッド数3
おわった id=12
現在のスレッド数3
おわった id=13
現在のスレッド数3
おわった id=14
現在のスレッド数3
おわった id=15
現在のスレッド数3
おわった id=16
現在のスレッド数3
おわった id=17
現在のスレッド数2
おわった id=18
現在のスレッド数1
おわった id=19
現在のスレッド数0

参照

Class Poco::Thread

Threadを使ってみる(エラーハンドリング) | DIGI-CON 技術部

POCO::Foundationでデザインパターン - マルチスレッド編 - (1/3):CodeZine(コードジン)