Pass Multiple Arguments into Std::Thread

Pass multiple arguments into std::thread

You literally just pass them in std::thread(func1,a,b,c,d); that should have compiled if the objects existed, but it is wrong for another reason. Since there is no object created you cannot join or detach the thread and the program will not work correctly. Since it is a temporary the destructor is immediately called, since the thread is not joined or detached yet std::terminate is called. You could std::join or std::detach it before the temp is destroyed, like std::thread(func1,a,b,c,d).join();//or detach .

This is how it should be done.

std::thread t(func1,a,b,c,d);
t.join();

You could also detach the thread, read-up on threads if you don't know the difference between joining and detaching.

Passing multiple arguments to a threaded function

When using C++11 you could use a lambda function which may use (non-formal) parameter of the context. "Capturing"

Something like

void doIt (int a, int b) {  // do something, your workForThread
}

..
int a = 1;
int b = 2;

std:thread r ([=](){doIt (a, b); return 1;});

When only calling a single function juanchopanza answer may be somewhat more efficient since no new function will be created.

The lambda version allows you to configure more. Let say you are starting threads which calls in the end 2 functions out of 3. juanchopanza approach would require NAMED functions for each permutation.

At the moment I consider the difference of both approaches to be mostly a matter of taste.

When you like to read more about lambda functions

What is a lambda expression in C++11?

Difference of passing argument to std::thread, C++

t1:

This simply passes a copy of V to the thread.

t2:

Similarly to t1, a copy of V is passed to the thread, but the actual copy is made in the called thread instead of the caller thread. This is an important distinction because should V be altered or cease to exist by the time the thread begins, you will end up with either a different vector or Undefined Behavior.

t3:

This should fail to compile as the thread will move the vector into the LValue reference, which is supposed to be illegal.

t4:

This passes the vector by reference to the thread. Any modifications to the passed reference will be applied to V, provided that proper synchronisation is performed, of course.

How to pass multiple arguments to spawned threads (Mbed)?

You could use an std::tuple<> instead of defining a new struct. This is simpler in most cases, although as the number of argument members goes up, you might find yourself wanting a struct after all, to get names for them instead of having to std::get() by type or index.

There is unlikely to be any other way, as such callback systems typically only offer a single 'user data' pointer, and my brief googling about Mbed suggest it is the same.

How to pass and start multiple threads within a function?

This is how I would do it, using a recursive template function.
And std::async instead of std::thread

#include <future>
#include <chrono>
#include <thread>
#include <iostream>

void test1(int /*i*/, double /*d*/)
{
std::cout << "Test1 start\n";
std::this_thread::sleep_for(std::chrono::milliseconds(300));
std::cout << "Test1 done\n";
}

void test2(bool)
{
std::cout << "Test2 start\n";
std::this_thread::sleep_for(std::chrono::milliseconds(500));
std::cout << "Test2 done\n";
}

//-----------------------------------------------------------------------------
// Recursive template function that will start all passed functions
// and then waits for them to be finished one by one.
// this will still be limited by the slowest function
// so no need to store them in a collection or something

template<typename Fn, typename... Fns>
void run_parallel(Fn fn, Fns&&... fns)
{
// I prefer using std::async instead of std::thread
// it has a better abstraction and futures
// allow passing of exceptions back to the calling thread.

auto future = std::async(std::launch::async, fn);

// are there any more functions to start then do so
if constexpr (sizeof...(fns) > 0)
{
run_parallel(std::forward<Fns>(fns)...);
}

future.get();
}

//-----------------------------------------------------------------------------

int main()
{
std::cout << "main start\n";

// start all functions by creating lambdas for them
run_parallel(
[]() { test1(1, 1.10); },
[]() { test2(true); }
);

std::cout << "main done\n";
}

Array of threads and attempting to pass multiple arguments to function is not working?

thread myThread[nodeNumber];

This creates a number of default-initialized threads i.e threads that do not represent any thread of execution.

myThread[i](map, rank_matrix, adjacency_matrix[i], nodeNumber, i);

Does not initialize your threads.

I would suggest using a vector of threads like in this example

std::vector<std::thread> threads;

This does not create any actual threads. Just the container to hold them.

Then you can populate it like so:

for(int i = 0; i < nodeNumber; i++)  {
threads.push_back(std::thread(map, rank_matrix, adjacency_matrix[i], nodeNumber, i);
}

Passing any function with any number of arguments to another function

Use a variadic template with perfect forwarding of its parameters, eg:

#include <iostream>
#include <thread>

#define __PRETTY_FUNCTION__ __FUNCSIG__

template<class Function, class... Args>
void runFunctionInThread(Function f, Args&&... args) {
std::thread t(f, std::forward<Args>(args)...);
t.detach();
}

void isolatedFunc1() { std::cout << __PRETTY_FUNCTION__ << "\n"; }
void isolatedFunc2(int value) { std::cout << __PRETTY_FUNCTION__ << " value is " << value << "\n"; }
void isolatedFunc3(int value1, int value2) { std::cout << __PRETTY_FUNCTION__ << " value1+value2 is " << value1 + value2 << "\n"; }

int main()
{
runFunctionInThread(&isolatedFunc1);
runFunctionInThread(&isolatedFunc2, 2);
runFunctionInThread(&isolatedFunc3, 3, 3);
}

However, this is fairly redundant since std::thread can handle this directly for you, so you don't need runFunctionInThread() at all, eg:

int main()
{
std::thread(&isolatedFunc1).detach();
std::thread(&isolatedFunc2, 2).detach();
std::thread(&isolatedFunc3, 3, 3).detach();
}


Related Topics



Leave a reply



Submit