2012-09-03 2 views
2

내 메인 스레드가 더 긴 계산을 수행하고 있습니다. 그 시간 동안 두 번째 스레드가 실행되어야합니다 (일종의 계산 감시/통계). 계산이 끝나면 감시 스레드를 중지해야합니다. 공유 플래그 변수를 사용하는 고전적인 접근법이 사용됩니다 (c.f. How to stop a running thread safely on user request?).사용자 요청시 tbb 스레드 중지

#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 

여기에 무슨 일이 일어나고 있습니까? 미리 답변 해 주셔서 감사합니다.

+0

코드에서 결과'Foo', 당신은 메인에서 만든'Foo'로 구성 복사합니다. –

+0

아, 스레드 fooThread (foo); 실제로 나의 foo를 복사하고있다 나는 위의 한 줄을 instanciated했다! 어떻게 참조 할 수 있습니까? –

+0

공유 데이터를 보유하는 기본 구조에 대한 참조를 매개 변수로 사용하고 저장하는'Foo'의 생성자를 만듭니다. –

답변

0

David, 유용한 힌트를 제공해 주셔서 감사합니다. 공유 데이터에 대한 참조가있는 Foo 생성자는 tbb 만 사용하면됩니다. 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