6

I am very new to C++.

I have a class, and I want to create a thread inside a class's function. And that thread(function) will call and access the class function and variable as well. At the beginning I tried to use Pthread, but only work outside a class, if I want to access the class function/variable I got an out of scope error. I take a look at Boost/thread but it is not desirable because of I don't want to add any other library to my files(for other reason).

I did some research and cannot find any useful answers. Please give some examples to guide me. Thank you so much!

Attempt using pthread(but I dont know how to deal with the situation I stated above):

#include <pthread.h>

void* print(void* data)
{
    std::cout << *((std::string*)data) << "\n";
    return NULL; // We could return data here if we wanted to
}

int main()
{
    std::string message = "Hello, pthreads!";
    pthread_t threadHandle;
    pthread_create(&threadHandle, NULL, &print, &message);
    // Wait for the thread to finish, then exit
    pthread_join(threadHandle, NULL);
    return 0;
}
Motti
  • 110,860
  • 49
  • 189
  • 262
user1701840
  • 1,062
  • 3
  • 19
  • 27
  • 1
    Can you post your attempts? that might shed some light on what you are trying to say :) – qdii Nov 03 '12 at 02:39
  • it might also be helpful if you state the platform you're using. – Eli Algranti Nov 03 '12 at 02:42
  • 4
    You *really* should use Boost.Thread or the standard thread library for this. If you do not, you will either end up with a suboptimal solution, or you will end up having to reimplement the functionality that those libraries already have. – Mankarse Nov 03 '12 at 02:42
  • I am using NS3, a networking simulator – user1701840 Nov 03 '12 at 02:42
  • Since you are new at c++ and thread, i recommend you to start with a easy approach like using OpenMP http://openmp.org/wp/. – dreamcrash Nov 03 '12 at 02:42
  • You attempt looks fine, you just need to `#include ` and `#include `. – Mankarse Nov 03 '12 at 02:43
  • Could you kindly post some example of using std::thread in class functions? – user1701840 Nov 03 '12 at 02:44
  • My attempt doesn't work because the print() function are not allow to access class's variable and functions. My attempt is only for simple case where there is no class involved. – user1701840 Nov 03 '12 at 02:45
  • I've put an example [here](http://liveworkspace.org/code/a1a0f659396788892809767cb16b6243). – Mankarse Nov 03 '12 at 02:52

2 Answers2

12

You can pass a static member function to a pthread, and an instance of an object as its argument. The idiom goes something like this:

class Parallel
{
private:
    pthread_t thread;

    static void * staticEntryPoint(void * c);
    void entryPoint();

public:
    void start();
};

void Parallel::start()
{
    pthread_create(&thread, NULL, Parallel::staticEntryPoint, this);
}

void * Parallel::staticEntryPoint(void * c)
{
    ((Parallel *) c)->entryPoint();
    return NULL;
}

void Parallel::entryPoint()
{
    // thread body
}

This is a pthread example. You can probably adapt it to use a std::thread without much difficulty.

Wug
  • 12,956
  • 4
  • 34
  • 54
  • um..why does the staticEntryPoint call the thread body inside another function? Why not just do it inside staticEntryPoint? – user1701840 Nov 03 '12 at 02:52
  • 1
    @user1701840: The thread body *could* be put in `staticEntryPoint`, but since it is a static function, it would probably be less convenient (as member accesses would have to be prefaced by `c->` for example). – Mankarse Nov 03 '12 at 02:54
  • I think the staticEntryPoint has to have the same signature on both implementation and declaration? – user1701840 Nov 03 '12 at 03:04
  • +1: @user1701840 What this shows is how to start a pthread using a static class function as the thread-proc, in this case `staticEnryPoint()`. The thread-data is an object instance that can be dereferenced to the object you want the thread to use. The static function is simply taking the object pointer (passed as a void \*) and forwarding to an object *member* (which has implicit access to member funds, vars, etc). That said, I *strongly* advise you use either boost threads or std::thread to take care of most all of this for you. – WhozCraig Nov 03 '12 at 03:20
  • @Mankarse: whoops. I remembered halfway through that pthread_create expects a function pointer returning void * and updated the definition but not the declaration. You missed that I forgot a semicolon after my class definition though :D – Wug Nov 03 '12 at 05:36
9
#include <thread>
#include <string>
#include <iostream>

class Class
{
public:
    Class(const std::string& s) : m_data(s) { }
    ~Class() { m_thread.join(); }
    void runThread() { m_thread = std::thread(&Class::print, this); }

private:
    std::string m_data;
    std::thread m_thread;
    void print() const { std::cout << m_data << '\n'; }
};

int main()
{
    Class c("Hello, world!");
    c.runThread();
}
Jonathan Wakely
  • 166,810
  • 27
  • 341
  • 521
  • Quick question: Why do I need to pass `this` into the thread constructor? – Mushy Oct 11 '17 at 15:23
  • Because `Class::print` is a non-static member function, so it has to be run on an object. How is the new thread supposed to know which object to call it on if you don't tell it? – Jonathan Wakely Oct 11 '17 at 17:18
  • Thank you for the explanation above. I'm confused by the `std::thread` constructor which appears to take `rvalues` and here `m_thread = std::thread(&Class::print, this);` an `lvalue` reference is being passed in. Can you please clarify this for me? I'll ask a question for you to answer if you prefer; – Mushy Oct 11 '17 at 18:24
  • @Mushy I suggest you ask a new question, instead of misusing comments. It doesn't take rvalue references, it takes forwarding references, and `&Class::print` is not a reference of any kind. Again, please ask your own question to understand this, don't use comments on this answer. – Jonathan Wakely Oct 12 '17 at 18:25
  • Thank you Jonathan. I have asked the question you suggested [here](https://stackoverflow.com/questions/46698832/stdthread-constructor-pass-by-reference-when-using-a-class-member-function) if you would like to take the time and provide an answer. – Mushy Oct 12 '17 at 19:23