Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it safe to pass arguments by reference into a std::thread function?

#include <thread>
#include <string>
#include <vector>
#include <chrono>

using namespace std;

void f(const vector<string>& coll)
{
    this_thread::sleep_for(1h);

    //
    // Is coll guaranteed to be valid before exiting this function?
    //
}

int main()
{
    {
        vector<string> coll(1024 * 1024 * 100);
        thread(f, coll).detach();
    }

    //
    // I know std::thread will copy arguments into itself by default, 
    // but I don't know whether these copied objects are still valid
    // after the std::thread object has been destroyed.
    //

    while (true);
}

Is it safe to pass arguments by reference into a std::thread function?

like image 755
xmllmx Avatar asked Jan 05 '17 03:01

xmllmx


People also ask

Can you pass by reference to a thread?

If you need to pass the argument to a thread by reference, it must be wrapped in a reference wrapper. This is quite straightforward with the helper function std::ref .

How do you pass a parameter to a thread in C++?

In c++11 to pass a referenceto a thread, we have std::ref(). std::thread t3(fun3, std::ref(x)); In this statement we are passing reference of x to thread t3 because fun3() takes int reference as a parameter.

How do threads pass arguments?

For cases where multiple arguments must be passed, this limitation is easily overcome by creating a structure which contains all of the arguments, and then passing a pointer to that structure in the pthread_create() routine. All arguments must be passed by reference and cast to (void *).

Is std :: thread copyable?

std::thread::operator= thread objects cannot be copied (2).

How do you pass arguments to a thread function?

The arguments to the thread function are moved or copied by value. If a reference argument needs to be passed to the thread function, it has to be wrapped (e.g., with std::ref or std::cref). So, you might use std::reference_wrapper through std::ref / std::cref: auto thread1 = std::thread (SimpleThread, std::ref (a));

How do you pass a reference to a thread function?

(or std::cref instead of std::ref, as appropriate). Per notes from cppreference on std:thread: The arguments to the thread function are moved or copied by value. If a reference argument needs to be passed to the thread function, it has to be wrapped (e.g. with std::ref or std::cref ).

Why do we need to wrap a thread parameter in C++?

If a reference argument needs to be passed to the thread function, it has to be wrapped (e.g. with std::ref or std::cref ). The capture, sensibly, defaults to capture by value because otherwise things would fail horribly if the parameter went away before the thread could read it.

When passing an argument to a procedure what should be considered?

When passing an argument to a procedure, be aware of several different distinctions that interact with each other: Whether the underlying programming element is modifiable or nonmodifiable Whether the argument data type is a value type or a reference type


2 Answers

As @T.C.'s comment, you're not passing reference to thread, you just make a copy of the vector in the thread:

thread(f, coll).detach(); // It's NOT pass by reference, but makes a copy.

If you really want to pass by reference, you should write this:

thread(f, std::ref(coll)).detach(); // Use std::ref to pass by reference

Then the code will get segment fault if the thread tries to access the vector, since when the thread runs, it's very likely the vector is already destructed (because it went out of it's scope in the main program).

So to your question:

Is it safe to pass arguments by reference into a std::thread function?

  • It is safe if you're sure the object remains valid during the thread's running;
  • It is NOT safe if the object is destructed, and you will get segment fault.
like image 156
Mine Avatar answered Oct 20 '22 22:10

Mine


  • Is coll guaranteed to be valid before exiting this function?

    • Updated: Yes. When you pass coll to the constructor of a std::thread in main function, because coll is an object, it is decay copied. This decay copy essentially moves the vector (so it becomes rvalue), which will bind to the coll parameter in f during the execution of the thread. (Thanks for the comment by @Praetorian)
  • Is it safe to pass arguments by reference into a std::thread function?

    • Your arguments are decay copied, so you actually never pass anything by reference to std::thread.
  • Reference for std::decay: http://www.cplusplus.com/reference/type_traits/decay/

  • The accepted answer in this question std::thread with movable, non-copyable argument explained what happens to the arguments passed to std::thread
like image 21
volatilevar Avatar answered Oct 20 '22 23:10

volatilevar