Dennis Dennis - 3 months ago 12
C++ Question

vectors and threading in C++

I would like to request for comments/ideas on how to resolve a vector and threading issue that is becoming a bit convoluted. I have researched the issue and have not found a working solution.

The intention is to have 5 person objects (stored in a vector) and then call each of their method to read a book concurrently (hence the threads). The read function contains a never ending loop.

I have the following code(simplified) set up:

class Book{
private:
// some data
public:
// some functions
};

class Person{
private:
// some data vars
int id;
Book abook;
public:
// some functions
Person(int index=0); // constructor
void readBook();
};

int main(void){

vector<Person>PersonsVector;
vector<thread> threads;
int num_of_persons = 5;

for(int i=0; i<num_of_persons; i++){
PersonsVector.push(Person(i)); //create different people
threads.push_back(thread(PersonsVector[i].readBook)); //read book in thread
}

// wait for threads to finnish or kill threads
for(auto& thread: threads)
threads.join();
}


My issue is really in how to call the readBook() function and push this to a thread

threads.push_back(thread(PersonsVector[i].readBook)); //read book in thread


Various variations for example these below lead to errors...

threads.push_back(thread(&PersonsVector[i].Person::readBook, this));
threads.push_back(thread(&Person::PersonsVector[i].Person::readBook, this));


Any ideas how I could resolve this issue?

Answer

A pointer-to-method must be called using a combination of a pointer specifying the class and method + an instance of said class on which to invoke said method.

This... thing:

&Person::PersonsVector[i].Person::readBook

actually says...

  • Get me the class Person,
  • then a vector within an unspecified instance of Person, which does not contain any such vector...
  • then an index i within that invalid vector,
  • then somehow get the constructor of that instance,
  • then somehow get a method readBook() from within that constructor.

See the problem? That's invalid syntax in so many varied ways.

The correct syntaxes are as follows:

  • For the pointer-to-method: &Person::readBook
  • For the instance: PersonsVector[i]

...and you need to give these to std::thread via some mechanism that will bundle the pointer-to-method and instance and make them callable for you - such as a lambda, std::bind, etc. - something like this:

std::thread theThread{
    [] // not sure which capture is needed... :/
    {
        (someInstance.*pointerToMethod)(the, args);
        // i.e.
        (PersonsVector[i].*readBook)();
    }
};