Start Thread With Member Function

Start thread with member function

#include <thread>
#include <iostream>

class bar {
public:
void foo() {
std::cout << "hello from member function" << std::endl;
}
};

int main()
{
std::thread t(&bar::foo, bar());
t.join();
}

EDIT:
Accounting your edit, you have to do it like this:

  std::thread spawn() {
return std::thread(&blub::test, this);
}

UPDATE: I want to explain some more points, some of them have also been discussed in the comments.

The syntax described above is defined in terms of the INVOKE definition (§20.8.2.1):

Define INVOKE (f, t1, t2, ..., tN) as follows:

  • (t1.*f)(t2, ..., tN) when f is a pointer to a member function of a class T and t1 is an object of type T or a reference to an object of
    type T or a reference to an object of a type derived from T;
  • ((*t1).*f)(t2, ..., tN) when f is a pointer to a member function of a class T and t1 is not one of the types described in the previous
    item;
  • t1.*f when N == 1 and f is a pointer to member data of a class T and t 1 is an object of type T or a

    reference to an object of type T or a reference to an object of a

    type derived from T;
  • (*t1).*f when N == 1 and f is a pointer to member data of a class T and t 1 is not one of the types described in the previous item;
  • f(t1, t2, ..., tN) in all other cases.

Another general fact which I want to point out is that by default the thread constructor will copy all arguments passed to it. The reason for this is that the arguments may need to outlive the calling thread, copying the arguments guarantees that. Instead, if you want to really pass a reference, you can use a std::reference_wrapper created by std::ref.

std::thread (foo, std::ref(arg1));

By doing this, you are promising that you will take care of guaranteeing that the arguments will still exist when the thread operates on them.


Note that all the things mentioned above can also be applied to std::async and std::bind.

Start thread with member function (with inheritance)

You might simply make set virtual:

struct Foo
{
// ...
virtual void set(int x);
};

struct Bar : Foo
{
void set(int x) override;
};

Starting a member function with arguments in a separate thread

Just add the arguments to the thread's constructor:

QString a("test");
std::thread thr(&MyClass::doStuff, this, a);

As your function accepts a reference you should use std::ref() like this:

MyClass::doStuff(QString& str) { /* ... */ }

// ...

QString a("test");
std::thread thr(&MyClass::doStuff, this, std::ref(a)); // wrap references

In C++, How a std::thread can call a member function without creating an object?

how td_1 and td_2 called the member function operator() of class H without an object of class H?

td_1 and td_2 does create objects of type H. Those objects are temporaries. Next, those supplied function object(which are temporaries in this case) are moved/copied into the storage belonging to the newly created thread of execution and invoked from there.

You can confirm this by adding a default constructor and move constructor inside class H as shown below:

#include<iostream>
#include<thread>

class H {
public:
void operator()(){
printf("This is H(), I take no argument\n");
}

void operator()(int x){
printf("This is H(), I received %d \n",x);
}
//default constructor
H()
{
std::cout<<"default constructor called"<<std::endl;
}
//move constructor
H(H&&)
{
std::cout<<"move constructor called"<<std::endl;
}

};

int main(){

int param = 0xD;

std::thread td_1 = std::thread(H());
std::thread td_2 = std::thread(H(),param);

td_1.join();
td_2.join();


return 0;
}

The output of the above program is:

default constructor called
move constructor called
move constructor called
default constructor called
move constructor called
move constructor called
This is H(), I take no argument
This is H(), I received 13

Starting thread with member function

But here I see only passing reference to member function.

The documentation says to the ThreadStart that it is a delegate. It

"represents the method that executes on a Thread.

When a managed thread is created, the method that executes on the thread is represented by a ThreadStart delegate"


Thread should start from function which should be static.

This is not necessarily true. The function does not have to be static.

The documentation shows both examples. Using a static method and using an instance method:

class Test
{
static void Main()
{
// To start a thread using a static thread procedure, use the
// class name and method name when you create the ThreadStart
// delegate. Beginning in version 2.0 of the .NET Framework,
// it is not necessary to create a delegate explicitly.
// Specify the name of the method in the Thread constructor,
// and the compiler selects the correct delegate. For example:
//
// Thread newThread = new Thread(Work.DoWork);
//
ThreadStart threadDelegate = new ThreadStart(Work.DoWork);
Thread newThread = new Thread(threadDelegate);
newThread.Start();

// To start a thread using an instance method for the thread
// procedure, use the instance variable and method name when
// you create the ThreadStart delegate. Beginning in version
// 2.0 of the .NET Framework, the explicit delegate is not
// required.
//
Work w = new Work();
w.Data = 42;
threadDelegate = new ThreadStart(w.DoMoreWork);
newThread = new Thread(threadDelegate);
newThread.Start();
}
}

class Work
{
public static void DoWork()
{
Console.WriteLine("Static thread procedure.");
}
public int Data;
public void DoMoreWork()
{
Console.WriteLine("Instance thread procedure. Data={0}", Data);
}
}

EDIT:

In respect to the type delegate the documentation says:

A delegate is a type that represents references to methods with a particular parameter list and return type.

In this tutorial on MSDN on deleagates you can see how it can be instantiated using the new keyword:

Instantiating a delegate Once a delegate type has been declared, a delegate object must be created and associated with a particular method. Like all other objects, a new delegate object is created with a new expression.

That means that since Loop and ThreadStart have the same return type, namely void and the same parameter list, (here empty) you can instatiate the delegate using the name of the instance method Loop.

EDIT 2:

I just was confused about using member function without reference.

This works because you declare the thread in the same class as where the method is declared.

May be there is implicit way of passing this reference?

In this context, the answer is yes. If you call a method inside a class or use the name as delegate (pointer to the method) then the this is implicit.

Start thread with derived class's member function

Pass std::ref(myInstance). Note that std::thread constructor will make a copy of the arguments passed to it (see here), and you can't copy a myAbstractClass.

(Then, all of this will still work because std::thread functionality is described in terms of std::invoke, which unwraps the std::reference_wrapper obtained by std::ref and calls the pointer to member function onto it. See here).

Starting a thread from a member function while inside another class's member function

You likely have to manage two instances:

  • An instance of Foo
  • A thread executing a member function of Foo

That leads to the following sketch of a class Bar:

#include <iostream>
#include <thread>

struct Foo{
void print(std::string s) { // by value!
std::cout << s;
}
};

class Bar{
public:
void hello() {
// Ensure the thread is not running
// (Only one thread is supported in this example)
if( ! foo_thread.joinable()) {
// Move a newly constructed thread to the class member.
foo_thread = std::thread(
&Foo::print, // pointer to member function of Foo
&foo, // pointer to the instance of Foo
"hello\n" // arguments by value
);
}
}

~Bar() {
// Ensure the thread has been started.
if(foo_thread.joinable()) {
// This will block until the thread has finished.
foo_thread.join();
}
}

private:
Foo foo;
std::thread foo_thread;
};

int main()
{
Bar bar;
bar.hello();
}

Note: The thread is not detached. A detached (not maintained properly) running thread, will get killed at end of the program and resources used by that thread (e.g.: file handles) might not be returned to the system.

Java - start thread with member function

The java.lang.Thread class is not essentially different from any other Java class. It has methods, and when you call them, they do what they do.

A java.lang.Thread is not a thread, in exactly the same way that a java.awt.Window instance is not a window. Threads and windows belong to the operating system, and the corresponding Java objects are the "handles" that you use to interface with the operating system. The Thread method that creates a new operating system thread is called t.start().

Suppose you define a class that extends Thread

class MyThread extends Thread {
...
public void saveData(...) { ... }
...
}

what would happen if I create an object of the child class and call saveData() on that object.?

You're asking us? But you are the person who wrote the method!! When your program calls my_thread.saveData(...), it'll be like calling any other method that you wrote in any other class that you defined. You are the one who wrote the method. It'll do whatever you put inside those curly braces.


The only thing that's even slightly magic about the Thread class is the start() method. If you write this:

class MyClass extends Thread {
...
public void saveData(...) { ... }
public void run() { ... }
...
}

Then when your program calls new MyThread().start(), the start method will "magically" create a new thread, and the new thread will call the run() method...

...which you also wrote, and which will do whatever you put inside its curly braces.

If you want saveData() to be called in the new thread, then make sure that it gets called from somewhere within the run() method.

C++11 multithreading with class member function [duplicate]

You need to pass two things: a pointer-to-member, and the object. You cannot call a non-static member function (like Gamma) in C++ without an object. The correct syntax would be:

std::thread gamma_thread(&Beta::Gamma, // the pointer-to-member
my_beta, // the object, could also be a pointer
5); // the argument

You can think of my_beta here as being the first argument to Gamma(), and 5 as the second.



Related Topics



Leave a reply



Submit