2

私のメインスレッドはより長い計算を行っています。その間、2番目のスレッドを実行する必要があります(一種の計算監視/統計)。計算が終了すると、監視スレッドを停止する必要があります。共有フラグ変数を使用する従来のアプローチが使用されます(ユーザーの要求に応じて実行中のスレッドを安全に停止する方法を参照)。

#include <iostream>

#include "tbb/compat/thread"
#include "tbb/atomic.h"
#include "tbb/spin_mutex.h"

using namespace tbb;
using namespace std;


class Foo {
    bool _stop;
    spin_mutex _stopMutex;

public:
    Foo();
    void operator()();
    bool stop();
    void stop(bool);
};

Foo::Foo() {
    _stop = false;
}

bool Foo::stop() {
    spin_mutex::scoped_lock lock(_stopMutex);
    return _stop;
}

void Foo::stop(bool stop) {
    spin_mutex::scoped_lock lock(_stopMutex);
    _stop = stop;
    cout << "Foo::stop(bool) new value: " << _stop << endl;
}

void Foo::operator ()() {
    int i = 0;
    while (true) {
        cout << "   Foo::operator() still alive " << i << endl;
        {
            spin_mutex::scoped_lock lock(_stopMutex);
            if (_stop) {
                cout << "   Foo::operator() is asked to finish" << endl;
                break;
            }
        }
        if (i > 15) {
            spin_mutex::scoped_lock lock(_stopMutex);
            _stop = true;;
        }
        sleep(1);
        ++i;
    }
}

int main() {
    Foo foo;
    thread fooThread(foo);

    cout << "starting longer calculation" << endl;
    int sum;
    for (int i = 0; i < 3; ++i) {
        sum += i;
        sleep(1);
    }
    cout << "finished longer calculation" << endl;

    for (int i = 0; i < 5; ++i) {
        foo.stop(true);
        cout << "main() stop=" << foo.stop() << endl;
        sleep(1);
    }

    cout << "main() calling join()" << endl;
    fooThread.join();
    cout << "main() fooThread joined" << endl;

    return 0;
}

ただし、共有変数はスレッド間で共有されません。各スレッドには独自のインスタンスがあるようです。監視スレッドは、それ自体が停止するまで停止しません。出力を見てください:

starting longer calculation
   Foo::operator() still alive 0
   Foo::operator() still alive 1
   Foo::operator() still alive 2
finished longer calculation
Foo::stop(bool) new value: 1
main() stop=1
   Foo::operator() still alive 3
Foo::stop(bool) new value: 1
main() stop=1
   Foo::operator() still alive 4
   Foo::operator() still alive 5
Foo::stop(bool) new value: 1
main() stop=1
   Foo::operator() still alive 6
Foo::stop(bool) new value: 1
main() stop=1
   Foo::operator() still alive 7
Foo::stop(bool) new value: 1
main() stop=1
   Foo::operator() still alive 8
main() calling join()
   Foo::operator() still alive 9
   Foo::operator() still alive 10
   Foo::operator() still alive 11
   Foo::operator() still alive 12
   Foo::operator() still alive 13
   Foo::operator() still alive 14
   Foo::operator() still alive 15
   Foo::operator() still alive 16
   Foo::operator() still alive 17
   Foo::operator() is asked to finish
main() fooThread joined

ここで何が起こっているのですか?よろしくお願いします!

4

1 に答える 1

0

デビッド、すべての有用なヒントをありがとう。tbbのみに固執する必要がある場合は、共有データへの参照を持つFooコンストラクターで問題ありません。Boostを使用して、より自己完結型のソリューションを見つけました。私が実際に意図したのはこれでした:

#include <iostream>

#include "boost/ref.hpp"
#include "boost/thread.hpp"

#include "tbb/atomic.h"

using namespace std;
using namespace tbb;

class Foo : public boost::thread {
    atomic<bool> _stop;

public:
    Foo();
    Foo(const Foo& rhs);
    void operator()();
    void stop();
};

Foo::Foo() : thread(ref(*this)) {
    cout << "Foo::Foo() called: " << this << endl;
    _stop = false;
}

Foo::Foo(const Foo& rhs) {
    cout << "Foo::Foo(const Foo&) called: " << this << endl;
    _stop = rhs._stop;
}

void Foo::stop() {
    _stop = true;
    cout << "Foo:stop() set _stop=" << _stop << endl;
    cout << "Foo:stop() calling interrupt()" << endl;
    interrupt();
    cout << "Foo:stop() calling join()" << endl;
    join();
    cout << "Foo:stop() joined" << endl;
}

void Foo::operator()() {
    int i = 0;
    while (!_stop) {
        cout << "   Foo::operator() still alive " << i << " (" << this << ")" << endl;
        if (_stop) {
            cout << "   Foo::operator() is asked to finish" << " (" << this << ")" << endl;
            break;
        }
        boost::this_thread::sleep( boost::posix_time::seconds(20) );
        ++i;
    }
}

int main() {
    Foo foo;

    cout << "starting longer calculation" << endl;
    int sum;
    for (int i = 0; i < 3; ++i) {
        sum += i;
        sleep(1);
    }
    cout << "finished longer calculation" << endl;

    foo.stop();

    return 0;
}

これにより、

Foo::Foo() called: 0x7fff6c7b9ff0
starting longer calculation
   Foo::operator() still alive 0 (0x7fff6c7b9ff0)
finished longer calculation
Foo:stop() set _stop=1
Foo:stop() calling interrupt()
Foo:stop() calling join()
Foo:stop() joined
于 2012-09-04T09:30:48.540 に答える