A quote from Nikolai Josuttis - Standard Library C++11:
Detached threads can easily become a problem if they use nonlocal resources. The problem is that
you lose control of a detached thread and have no easy way to find out whether and how long it runs.
Thus, make sure that a detached thread does not access any objects after their lifetime has ended. For
this reason, passing variables and objects to a thread by reference is always a risk. Passing arguments
by value is strongly recommended.
So further the author explains, that even if you pass a reference as a function argument to a thread, it still passes by value, so you must indicate the reference with std::ref.
I have these questions, see the code below:
void f(std::vector<int> V){...}
void g(std::vector<int>& V){...}
std::vector<int> V;
std::thread t1(f, V);
std::thread t2(f, std::ref(V));
std::thread t3(g, V);
std::thread t4(g, std::ref(V));
What are the differences in these 4 lines? Which lines are equivalent?
I am not joining or detaching thread, it's not about that, it's about the ways of passing the function argument.
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.
Related
As an example in pseudocode:
MultiThreadedWorker worker;
Foo()
{
const Vector position = CreatePosition();
worker.StartWorker(Position);
}
MultiThreadedWorker::StartWorker(const Vector& myPosition)
{
... Do a bunch of async work that keeps referencing myPosition ...
}
This seems to be working for now, but I don't understand why because it seems that myPosition would end up pointing to nothing long before StartWorker completed.
Assuming this isn't safe, is there any solution other than just passing around everything by value or ensuring it's all on the heap?
std::async copies const references
So yes, it is safe. For a discussion of why it does, see Why does std::async copy its const & arguments?
It is programmers responsibility to ensure that variable live long enough so that it is not destroyed before any access through pointers or references. This can be achieved through at least by one of the following:
Ensure the thread ends before destroying the variable. You can run .join() on the thread before leaving the scope.
Create object on the heap. Create it using make_shared and pass shared_ptr. This ensures the object lives until the last reference is destroyed.
Note that there is another problem with threads and shared objects. If one thread writes when another thread reads to the same object, then it is a data race which is Undefined Behavior. Thread synchronization mechanisms such as std::mutex can be used to avoid this.
Some time ago I was looking for a way to invoke std::async without the need of storing std::future, thus not blocking the execution at the end of the scope. I found this answer which uses a captured std::shared_ptr for an std::future, therefore allowing to make a nonblocking call to std::async.
Another way of deferring a destructor invocation is to prevent it from to be called at all. This can be achieved with in-place construction with operator new.
Consider this version that uses a static thread local storage for an in-place constructed std::future<void>:
template <class F>
void call_async(F&& fun) {
thread_local uint8_t buf[sizeof(std::future<void>)] = {0};
auto fut = new(buf) std::future<void>();
*fut = std::async(std::launch::async, [fun]() {
fun();
});
}
This version will not produce any heap-allocation related overhead, but it seems very illegal, though I am not sure why in particular.
I am aware that it is UB to use an object before it has been constructed, which is not the case. I am not sure why not calling delete in this case would resolve in UB (for heap allocation it is not UB).
Possible problems that I see:
calling a constructor on one object multiple times
race condition when modifying the state (inner std::promise I suppose)
https://ideone.com/C44cfe
UPDATE
Constructing an object in the static storage directly (as has mentioned IlCapitano in the comments) will block each time a move assignment is called (shared state will be destroyed blocking the thread which has removed last reference to it).
Not calling a destructor will case a leak because of not released references to the shared state.
It's undefined behaviour to end the lifetime of a non-trivial object without calling it's destructor, which happens as soon as there is a second call_async invocation.
"heap-allocation related overhead" is a misnomer if the only alternative is undefined behaviour. The future returned by async has to live somewhere.
The updated code has defined behaviour: it waits for the previous invocation to be done before launching the next one.
Calling std::async and ignoring the result sounds like "fire and forget". The simplest way to do that is to not use std::async, but to create a detached thread:
std::thread thr(func, data...);
thr.detach();
According to cppreference.com, the
std::thread constructor with no parameter means:
Creates new thread object which does not represent a thread.
My questions are:
Why do we need this constructor? And if we create a thread using this constructor, how can we "assign" a thread function later?
Why don't we have a "run(function_address)" method so that when constructed with no parameter, we can specify a function to "run" for that thread.
Or, we can construct a thread with a callable parameter (function, functors, etc.) but call a "run()" method to actually execute the thread later. Why is std::thread not designed in this way?
Your question suggests there might be some confusion and it would be helpful to clearly separate the ideas of a thread of execution from the std::thread type, and to separate both from the idea of a "thread function".
A thread of execution represents a flow of control through your program, probably corresponding to an OS thread managed by the kernel.
An object of the type std::thread can be associated with a thread of execution, or it can be "empty" and not refer to any thread of execution.
There is no such concept as a "thread function" in standard C++. Any function can be run in a new thread of execution by passing it to the constructor of a std::thread object.
why do we need this constructor?
To construct the empty state that doesn't refer to a thread of execution. You might want to have a member variable of a class that is a std::thread, but not want to associate it with a thread of execution right away. So you default construct it, and then later launch a new thread of execution and associate it with the std::thread member variable. Or you might want to do:
std::thread t;
if (some_condition) {
t = std::thread{ func1, arg1 };
}
else {
auto result = some_calculation();
t = std::thread{ func2, arg2, result };
}
The default constructor allows the object t to be created without launching a new thread of execution until needed.
And if we create a thread using this constructor, how can we "assign" a thread function later?
You "assign" using "assignment" :-)
But you don't assign a "thread function" to it, that is not what std::thread is for. You assign another std::thread to it:
std::thread t;
std::thread t2{ func, args };
t = std::move(t2);
Think in terms of creating a new thread of execution not "assigning a thread function" to something. You're not just assigning a function, that's what std::function would be used for. You are requesting the runtime to create a new thread of execution, which will be managed by a std::thread object.
Why don't we have a "run(function_address)" method so that when constructed with no parameter, we can specify a function to "run" for that thread.
Because you don't need it. You start new threads of execution by constructing a std::thread object with arguments. If you want that thread of execution to be associated with an existing object then you can do that by move-assigning or swapping.
Or, we can construct a thread with a callable parameter(function, functors, etc.) but call a "run()" method to actually execute the thread later. Why std::thread is not designed in this way?
Why should it be designed that way?
The std::thread type is for managing a thread of execution not holding a callable object for later use. If you want to create a callable object that can be later run on a new thread of execution there are lots of ways to do that in C++ (using a lambda expression, or std::bind, or std::function, or std::packaged_task, or a custom functor type). The job of std::thread is to manage a thread of execution not to hold onto a callable object until you want to call it.
The default constructor is provided such that an "empty" thread object can be created. Not all thread objects will be associated with a thread of execution at the time of construction of said object. Consider when the thread is a member of some type and that type has a default constructor. Consider another case that the thread type has no concept of a "suspended" thread, i.e. it can't be created in a suspended state.
The thread type doesn't have a "run" method of some sort since the one of the original design decisions (IIRC) was to have a "strong" association between the thread object and the thread of execution. Allowing threads to be "moved" makes that intent clearer (in my opinion). Hence moving an instance of a thread object to an "empty" object is clearer than attempting to "run" a thread.
It is conceivable that you can create a wrapper class of some sort that offers the "run" method, but I think this may be a narrower use case, and that can be solved given the API of the std::thread class.
The default constructor gives you then possibility to create array of threads:
thread my_threads[4];
for (int i=0; i<4; i++)
{
thread temp(func,...);
my_threads[i]=move(temp);
}
the thread created with default costructor "become" a "real" thread with the move costructor.
You can use thread with standard container if you need/like.
EDIT: Maybe lets firsts comment on the very last part:
3.2 Why std::thread is not designed in this way?
I don't know why exactly (there are surely advantages and disatvantages - see Jonathan Wakely's answer for a more details about the rational behind it), but it seems that c++11 std::thread is modelled much closer to pthreads than e.g. QT's or Java's QThread/Thread classes, which might be the source of your confusion.
As to the rest of your questions:
1.1 why do we need this constructor?
You might want to create a std::thread variable but don't directly start a thread (e.g. a class member variable or an element of a static array, es shown by alangab). It's not much different to an std::fstream that can be created without a filename.
1.2 And if we create a thread using this constructor, how can we "assign" a thread function later?
For example:
std::thread myThread;
// some other code
myThread = std::thread(foo());
Why don't we have a "run(function_address)" method so that when constructed with no parameter, we can specify a function to "run" for that thread.
I don't know, why it was designed like this, but I don't see the benefit a run method would have compared to above syntax.
3.1 Or, we can construct a thread with a callable parameter(function, functors, etc.) but call a "run()" method to actually execute the thread later.
You can simulate this by creating a lambda or std::function object and create the thread when you want to run the function.
auto myLambda = [=]{foo(param1, param2);};
// some other code
std::thread myThread(myLambda);
If you want to use the syntax you describe, I'd recommend to write your own Thread wrapper class (should only take a few dozen lines of code) that (optionally) also ensures that the thread is either detached or joined upon destruction of the wrapper, which is - in my opinion - the main problem with std::thread.
As the title of the question says, why C++ threads (std::thread and pthread) are movable but not copiable? What consequences are there, if we do make it copiable?
Regarding copying, consider the following snippet:
void foo();
std::thread first (foo);
std::thread second = first; // (*)
When the line marked (*) takes place, presumably some of foo already executed. What would the expected behavior be, then? Execute foo from the start? Halt the thread, copy the registers and state, and rerun it from there?
In particular, given that function objects are now part of the standard, it's very easy to launch another thread that performs exactly the same operation as some earlier thread, by reusing the function object.
There's not much motivation to begin with for this, therefore.
Regarding moves, though, consider the following:
std::vector<std::thread> threads;
without move semantics, it would be problematic: when the vector needs to internally resize, how would it move its elements to another buffer? See more on this here.
If the thread objects are copyable, who is finally responsible for the single thread of execution associated with the thread objects? In particular, what would join() do for each of the thread objects?
There are several possible outcomes, but that is the problem, there are several possible outcomes with no real overlap that can be codified (standardised) as a general use case.
Hence, the most reasonable outcome is that 1 thread of execution is associated with at most 1 thread object.
That is not to say some shared state cannot be provided, it is just that the user then needs to take further action in this regard, such as using a std::shared_ptr.
The C++11 standard says:
30.6.6 Class template future
(3) "The effect of calling any member function other than the destructor,
the move-assignment operator, or valid on a future object for which
valid() == false is undefined."
So, does it mean that the following code might encounter undefined behaviour?
void wait_for_future(std::future<void> & f)
{
if (f.valid()) {
// what if another thread meanwhile calls get() on f (which invalidates f)?
f.wait();
}
else {
return;
}
}
Q1: Is this really a possible undefined behaviour?
Q2: Is there any standard compliant way to avoid the possible undefined behaviour?
Note that the standard has an interesting note [also in 30.6.6 (3)]:
"[Note: Implementations are encouraged
to detect this case and throw an object of type future_error with an
error condition of future_errc::no_state. —endnote]"
Q3: Is it ok if I just rely on the standard's note and just use f.wait() without checking f's validity?
void wait_for_future(std::future<void> & f)
{
try {
f.wait();
}
catch (std::future_error const & err) {
return;
}
}
EDIT: Summary after receiving the answers and further research on the topic
As it turned out, the real problem with my example was not directly due to parallel modifications (a single modifying get was called from a single thread, the other thread called valid and wait which shall be safe).
The real problem was that the std::future object's get function was accessed from a different thread, which is not the intended use case! The std::future object shall only be used from a single thread!
The only other thread that is involved is the thread that sets the shared state: via return from the function passed to std::async or calling set_value on the related std::promise object, etc.
More: even waiting on an std::future object from another thread is not intended behaviour (due to the very same UB as in my example#1). We shall use std::shared_future for this use case, having each thread its own copy of an std::shared_future object. Note that all these are not through the same shared std::future object, but through separate (related) objects!
Bottom line:
These objects shall not be shared between threads. Use a separate (related) object in each thread.
A normal std::future is not threadsafe by itself. So yes it is UB, if you call modifying functions from multiple threads on a single std::future as you have a potential race condition. Though, calling wait from multiple threads is ok as it's const/non-modifying.
However, if you really need to access the return value of a std::future from multiple threads you can first call std::future::share on the future to get a std::shared_future which you can copy to each thread and then each thread can call get. Note that it's important that each thread has its own std::shared_future object.
You only need to check valid if it is somehow possible that your future might be invalid which is not the case for the normal usecases(std::async etc.) and proper usage(e.g.: not callig get twice).
Futures allow you to store the state from one thread and retrieve it from another. They don't provide any further thread safety.
Is this really a possible undefined behaviour?
If you have two threads trying to get the future's state without synchronisation, yes. I've no idea why you might do that though.
Is there any standard compliant way to avoid the possible undefined behaviour?
Only try to get the state from one thread; or, if you genuinely need to share it between threads, use a mutex or other synchronisation.
Is it ok if I just rely on the standard's note
If you known that the only implementations you need to support follow that recommendation, yes. But there should be no need.
and just use f.wait() without checking f's validity?
If you're not doing any weird shenanigans with multiple threads accessing the future, then you can just assume that it's valid until you've retrieved the state (or moved it to another future).