2012-06-09 2 views
0

으로 부스트 1.49와 MSVC10을 사용하고 있습니다. boost::thread하면호출 가능한 객체에 액세스하기 boost :: thread가 생성되었습니다

는 호출 객체 1로 구성되고, 나는 callabe 객체에 도착 어떻게 그 객체는 멤버 함수 또는 나는 thread의 컨텍스트 외부 에서 액세스 할 변수가?

예를 들어 main()에 로컬 인 vector<boost::thread*>에 저장된 5 개의 작업자 스레드를 생성하는 간단한 응용 프로그램을 구현했습니다. 이 스레드들 각각은 생성자에 char 매개 변수 하나를 취하는 호출 가능 객체 Gizmo으로 인스턴스화됩니다. 이 charGizmo 클래스에 std::string 멤버 변수로 저장됩니다. 각 스레드는 cout으로 저장되고 string으로 저장되고 250ms 동안 잠자기됩니다. 어쨌든 의 값이 "죽습니다"가 될 때까지 계속이 루프에서 영원히 계속됩니다.

Short, Self Contained, (Hopefully) Correct, Example :

  1. vector
  2. 의 첫 threadGizmo 객체가 thread에 포함하기하기 :

    #include <cstdlib> 
    #include <string> 
    #include <memory> 
    #include <vector> 
    using namespace std; 
    
    #include <boost/thread.hpp> 
    #include <boost/date_time/posix_time/posix_time.hpp> 
    
    boost::mutex cout_mtx; 
    
    class Gizmo 
    { 
    public: 
        Gizmo(const string& state) : state_(state) {}; 
        Gizmo(Gizmo&& rhs) : state_(std::move(rhs.state_)) {}; 
        virtual ~Gizmo() 
        { 
         bool b = true; 
        } 
        void operator()(); 
    
        string state_; 
    }; 
    
    void Gizmo::operator()() 
    { 
        while(state_ != "die") 
        { 
         { 
          boost::mutex::scoped_lock scoped_lock(cout_mtx); 
          cout << state_ << flush; 
         } 
         boost::this_thread::sleep(boost::posix_time::milliseconds(250)); 
        } 
    } 
    
    boost::thread* start_thread(char c) 
    { 
        Gizmo g(string(1,c)); 
        return new boost::thread(g); 
    } 
    
    int main() 
    { 
        vector<boost::thread*> threads; 
    
        string d=".*x%$"; 
        for(string::const_iterator it = d.begin(); it != d.end(); ++it) 
        { 
         threads.push_back(start_thread(*it)); 
        } 
    
        for(auto th = threads.begin(); th != threads.end(); ++th) 
         (*th)->join(); 
    } 
    

    지금 나는 것 main()의 코드 변경을 만들고 싶어

  3. 세트 state_ "die"

스레드 내에서 Gizmo을 얻으려면 어떻게해야합니까? 이러한 맥락에서

for(auto th = threads.begin(); th != threads.end(); ++th) 
{ 
    boost::this_thread::sleep(boost::posix_time::seconds(1)); 
    Gizmo& that_gizmo = (*th)-> ??? ; // WHAT DO I DO? 
    that_gizmo.state_ = "die"; 
} 

(1) 호출 객체operator()class을 의미한다.

답변

1

boost::thread은 호출 대상 객체를 가져 오는 기능을 제공하지 않습니다.boost::thread에는 기본 생성자가 있으므로 스레드의 진입 점 역할을하는 호출 가능 유형이나 함수를 알 수 없습니다. 또한 boost::thread이 유형 삭제를 수행하지 않으면 동일한 콜렉션 또는 스레드 풀의 다른 진입 점을 가진 스레드를 더 이상 관리 할 수 ​​없습니다. 예를 들어 std::vector< boost::thread<Gizmo> >Gizmo 개의 스레드 만 관리 할 수 ​​있으며 std::vector<boost::thread>Gizmo 개의 스레드와 Gizmo 개의 스레드를 관리 할 수 ​​있습니다. 대신 별도의리스트 Gizmoboost::thread 객체를 관리하는 데, 또는 함께 두 쌍 또는 두 std::pairboost::tuple 통해 연관 고려하는 새로운 형태를 생성

. 예를 들면 : 스레드가 엔트리 포인트에 사용되는 여러 유형을 가진 결국, 각 유형의 종료의 자신의 양식을 필요로하는 경우

std::vector< boost::tuple< boost::thread*, Gizmo > > threads; 

또한, boost::function를 통해 유형 삭제를 수행하는 것이 좋습니다. 예 : 모든 용액

void shutdown_gizmo(Gizmo&); 

boost::function< void() > fn = boost::bind(shutdown_gizmo, boost::ref(gizmo)); 

// The tuple now contains a function object, decoupling it from Gizmo objects, 
// and allowing other shutdown methods to be paired with threads. 
typedef boost::tuple< boost::thread*, boost::function< void() > > tuple_t; 
std::vector<tuple_t> threads; 

는 단지 Gizmo 객체의 범위를 유지할뿐만 아니라, 올바른 Gizmo 객체에 대한 핸들을 유지 조심. 의도하지 않게 실제 Gizmo 개체의 복사본에 대한 핸들을 확보하는 것이 매우 쉽습니다.

+0

이 클로리는 내 마지막 솔루션과 흡사합니다. –

1

클래스 대신 start_thread 클래스를 구현하면 함수 대신 함수에 액세스 할 수 있고 포인터에 대한 벡터를 유지할 수 있습니까? 의 라인을 따라 뭔가 (자세한 내용은 밖으로 다림질 할,이 중 어느 것도 시험되지 않음) :

class start_thread { 
public: 
    explicit start_thread(char c) : gizmo_(std::string(c,1)), t_(gizmo_) {} 
    void join() { t_.join();} 
    const Gizmo& callable() const { return gizmo_;} 
    Gizmo& callable() { return gizmo_;} 
private: 
    Gizmo gizmo_; 
    boost::thread t_; 
} 

당신은 boost::ref(gizmo_)로 스레드 생성자에 gizmo_을 통과해야합니다.

+0

+1 : 예, 할 수 있다고 생각합니다. 나는 어떤 종류의 캡슐화 장치를 만들기보다는 내장 시설을 사용할 수 있기를 바랬다. 당신이 제안한대로, 나는 또한'join_all()'타입 함수 등으로 어떤 종류의 컨테이너 클래스를 구현해야 할 것이다. 나는이 모든 것을 할 수있다. 내가 할 필요가 없다면 나는 오히려하지 않을 것입니다. –

+0

@JohnDibling 예, 불행한 점은 호출 가능 항목에 대한 핸들이 없지만 동기화를 복잡하게 만들 수 있다고 생각합니다. – juanchopanza

2

start_thread() 메소드는 스레드에 전달되는 임시 스택 객체를 생성합니다. 대신 main()에 Gizmo 객체의 벡터를 만든 다음 해당 벡터의 각 멤버 (Gizmo)를 boost의 스레드 생성자에 전달해야합니다. 주 기능의 벡터에 참조를 저장할 수있을 때 스레드의 호출 가능 객체를 구체적으로 가져와야하는 이유가 없습니다.

주 스레드와이를 검사하는 부스트 스레드 사이의 상태 설정을 동기화하는 것을 잊지 마십시오.

+0

+1 당신이 뭘보고 있는지, 다른 제안과 비슷합니다. 내가'Gizmo'와 다른'thread' 목록을 유지하기를 원하지 않는 이유는 스레드가 이미 데이터 멤버 내에 캡슐화 된'Gizmo'를 가지고 있기 때문입니다. 두 개의 개별 목록을 유지 관리하고 동기화를 유지하는 것은 복잡하지 않아야하는 복잡성 수준입니다. 적어도, 이상적인 세계에서 - 부스트는 분명히 그렇지 않습니다. –

관련 문제