我的类中的c ++ condition_variable wait_for谓词,std :: thread <unresolved overloaded =“”function =“”type =“”> error

时间:2016-09-19 04:07:59

标签: c++ multithreading c++11 condition-variable

我试图在我的类中使用一个线程,然后线程需要使用condition_variable,条件变量将被阻塞,直到谓词变为true。代码如下所示:

class myThreadClass{
    bool bFlag;
    thread t ;
    mutex mtx;
    condition_variable cv;

    bool myPredicate(){
      return bFlag;
    }

    int myThreadFunction(int arg){
       while(true){
           unique_lock<mutex> lck(mtx);
           if(cv.wait_for(lck,std::chrono::milliseconds(3000),myPredicate)) //something wrong?  
                cout<<"print something...1"<<endl 
           else
                cout<<"print something...2"<<endl 
       }
    }

    void createThread(){
        t = thread(&myThreadClass::myThreadFunction,this,10);//this is ok
    }

} ;

编译时的这段代码会抛出错误说:

  

“wait_for”行中未解决的重载函数类型。

然后我尝试将其修改为:

if(cv.wait_for(lck,std::chrono::milliseconds(3000),&myThreadClass::myPredicate))

但仍有错误。

3 个答案:

答案 0 :(得分:4)

谓词需要在没有任何上下文的情况下进行调用。您试图在非静态类成员上调用它,这需要一个操作对象。

您可以使用lambda函数捕获对象的上下文并将函数调用包装为合适的类型:

const std::chrono::milliseconds timeout( 3000 );
if( cv.wait_for( lck, timeout, [this]{ return myPredicate(); } ) )
    // ...

如果您因为条件变量而只创建了myPredicate,那么您可以取消它并使用它:

if( cv.wait_for( lck, timeout, [this]{ return bFlag; } ) )

答案 1 :(得分:4)

(指向一个)成员函数作为谓词的指针是不合适的,因为它需要一个对象被调用,所以你需要一个包装器来绑定成员函数到一个对象,并使其只有两个要比较的值可调用。

在C ++ 11中,您可以将成员函数绑定到对象:

class myThreadClass{

bool bFlag;
thread t ;
mutex mtx;
condition_variable cv;

bool myPredicate(){
  return bFlag;
}

int myThreadFunction(int arg){
   while(true){
       unique_lock<mutex> lck(mtx);
       if(cv.wait_for(lck,std::chrono::milliseconds(3000),std::bind(&myThreadClass::myPredicate,this))) //something wrong?  
            cout<<"print something...1"<<endl; 
       else
            cout<<"print something...2"<<endl; 
   }
}

void createThread(){
    t = thread(&myThreadClass::myThreadFunction,this,10);//this is ok
}
};

您可以在bind中使用占位符。

或者你可以使用lambda函数。

答案 2 :(得分:2)

是的,实际上最好的办法是......

auto myPredicate = [this]{ return bFlag; } 

然后使用

if (cv.wait_for(lck, std::chrono::milliseconds(3000), myPredicate))

这样您就可以取消myPrediate方法。