c++ condition_variable wait_for predicate in my class, std::thread <unresolved overloaded function type> error
Asked Answered
R

3

10

I am trying to use a thread within my class, then the thread needs to use a condition_variable, and the condition variable will be blocked until a predicate be changed to true. The code looks like this:

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
    }

} ;

This code on compilation throws an error saying:

unresolved overloaded function type in the line “wait_for”.

Then i try modify it to:

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

But there is still an error.

Ridotto answered 19/9, 2016 at 4:7 Comment(2)
if (cv.wait_for(lck, std::chrono::milliseconds(3000), [this]{ return myPredicate(); }))Libau
Use of predicate is wrong. That is how predicate can't be used.Undershorts
M
6

The predicate needs to be callable without any context. You are trying to invoke this on a non-static class member, which requires an object on which to operate.

You can use a lambda function to capture the object's context and wrap the function call into a suitable type:

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

If you only created myPredicate because of the condition variable, you can do away with it and just use this:

if( cv.wait_for( lck, timeout, [this]{ return bFlag; } ) )
Microscope answered 19/9, 2016 at 4:27 Comment(0)
U
4

A (pointer to a) member function as a predicate isn't suitable, since it requires an object to be called on, so you'll need a wrapper to bind the member function to an object and make it callable with just the two values to compare.

In C++11, you can bind a member function to an object:

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
}
};

you can use placeholders in bind.

Or you can use lambda functions.

Undershorts answered 19/9, 2016 at 4:35 Comment(0)
P
2

Yes, in fact the best way to do this is..

auto myPredicate = [this]{ return bFlag; } 

and then using

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

This way you can eliminate the myPrediate method.

Pinnacle answered 19/9, 2016 at 4:28 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.