'Comparison of methods for multithreading with multiple objects in C++

I'm working on C++ code for a 'manager' class that runs a process in multiple member objects in separate threads and returns a set of values. I see three basic ways I can implement this:

  1. create each thread with the member function for the relevant object and a callback mechanism to return the values;
  2. provide an auxiliary function in the manager class that calls the member function for a specified object and create separate threads with this auxiliary function; or
  3. create each thread with the member function for the relevant object (as in method #1) and pass pointers to variables to hold the return values.

My question is, are there compelling reasons to choose one method over the other, in terms of performance or other factors, keeping in mind the fact that the actual application would have an array or vector of an indeterminate number of objects (unlike the examples below)?

An example of the first method would look like this:

#include <thread>
#include <iostream>
#include <functional>

using namespace std;
using namespace std::placeholders;

typedef function<void(string, int)> Callback;

class Processor {
private:
    string name;
    Callback cb_func;

public:
    Processor(string nme, Callback f) : name(nme), cb_func(f) { }
    void do_stuff(int lim) { cb_func(name, rand() % lim); }
};

class Manager {
private:
    Processor *p0, *p1;

public:
    Manager() {
        p0 = new Processor("lizard", std::bind(&Manager::report, this, _1, _2));
        p1 = new Processor("ferret", std::bind(&Manager::report, this, _1, _2));
    }

    ~Manager() {
        delete p0;
        delete p1;
    }
    
    void manage() {
        thread t0 = thread(&Processor::do_stuff, p0, 100);
        thread t1 = thread(&Processor::do_stuff, p1, 100);

        t0.join();
        t1.join();
    }

    void report(string source, int value) {
        cout << source << " reports " << value << endl;
    }
};

int main() {
    Manager the_dude;
    the_dude.manage();
    return 0;
}

An example of the second method would look like this:

#include <thread>
#include <iostream>

using namespace std;

class Processor {
private:
    string name;

public:
    Processor(string nme) : name(nme) { }
    int do_stuff(int lim) { return rand() % lim; }
    string get_name() { return name; }
};

class Manager {
private:
    Processor *p0, *p1;

public:
    Manager() {
        p0 = new Processor("lizard");
        p1 = new Processor("ferret");
    }

    ~Manager() {
        delete p0;
        delete p1;
    }

    void work(Processor *p, int lim) {
        cout << p->get_name() << " reports " << p->do_stuff(lim) << endl;
    }
    
    void manage() {
        thread t0 = thread(&Manager::work, this, p0, 100);
        thread t1 = thread(&Manager::work, this, p1, 100);

        t0.join();
        t1.join();
    }
};

int main() {
    Manager the_dude;
    the_dude.manage();
    return 0;
}

And an example of the third method would look like this:

#include <thread>
#include <iostream>

using namespace std;

class Processor {
private:
    string name;

public:
    Processor(string nme) : name(nme) { }
    void do_stuff(int lim, string *nme, int *val) { *nme = name; *val = rand() % lim; }
};

class Manager
{
private:
    Processor *p0, *p1;
    string s0, s1;
    int v0, v1;

public:
    Manager() {
        p0 = new Processor("lizard");
        p1 = new Processor("ferret");
    }

    ~Manager() {
        delete p0;
        delete p1;
    }
    
    void manage() {
        thread t0 = thread(&Processor::do_stuff, p0, 100, &s0, &v0);
        thread t1 = thread(&Processor::do_stuff, p1, 100, &s1, &v1);

        t0.join();
        t1.join();
        
        report(s0, v0);
        report(s1, v1);
    }

    void report(string source, int value) {
        cout << source << " reports " << value << endl;
    }
};

int main()
{
    Manager the_dude;
    the_dude.manage();

    return 0;
}


Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source