In C++, during a class constructor, I started a new thread with this pointer as a parameter which will be used in the thread extensively (say, calling member functions). Is that a bad thing to do? Why and what are the consequences?
My thread start process is at the end of the constructor.
The consequence is that the thread can start and code will start executing a not yet fully initialized object. Which is bad enough in itself.
If you are considering that 'well, it will be the last sentence in the constructor, it will be just about as constructed as it gets...' think again: you might derive from that class, and the derived object will not be constructed.
The compiler may want to play with your code around and decide that it will reorder instructions and it might actually pass the this pointer before executing any other part of the code... multithreading is tricky
Main consequence is that the thread might start running (and using your pointer) before the constructor has completed, so the object may not be in a defined/usable state. Likewise, depending how the thread is stopped it might continue running after the destructor has started and so the object again may not be in a usable state.
This is especially problematic if your class is a base class, since the derived class constructor won't even start running until after your constructor exits, and the derived class destructor will have completed before yours starts. Also, virtual function calls don't do what you might think before derived classes are constructed and after they're destructed: virtual calls "ignore" classes whose part of the object doesn't exist.
Example:
struct BaseThread {
MyThread() {
pthread_create(thread, attr, pthread_fn, static_cast<void*>(this));
}
virtual ~MyThread() {
maybe stop thread somehow, reap it;
}
virtual void id() { std::cout << "base\n"; }
};
struct DerivedThread : BaseThread {
virtual void id() { std::cout << "derived\n"; }
};
void* thread_fn(void* input) {
(static_cast<BaseThread*>(input))->id();
return 0;
}
Now if you create a DerivedThread, it's a best a race between the thread that constructs it and the new thread, to determine which version of id() gets called. It could be that something worse can happen, you'd need to look quite closely at your threading API and compiler.
The usual way to not have to worry about this is just to give your thread class a start() function, which the user calls after constructing it.
Depends on what you do after starting the thread. If you perform initialization work after the thread has started, then it could use data that is not properly initialized.
You can reduce the risks by using a factory method that first creates an object, then starts the thread.
But I think the greatest flaw in the design is that, for me at least, a constructor that does more than "construction" seems quite confusing.
It can be potentially dangerous.
During construction of a base class any calls to virtual functions will not despatch to overrides in more derived classes that haven't yet been completely constructed; once the construction of the more derived classes change this changes.
If the thread that you kick-off calls a virtual function and it is indeterminate where this happens in relation to the completion of the construction of the class then you are likely to get unpredictable behaviour; perhaps a crash.
Without virtual functions, if the thread only uses methods and data of the parts of the class that have been constructed completely the behaviour is likely to be predictable.
I'd say that, as a general rule, you should avoid doing this. But you can certainly get away with it in many circumstances. I think there are basically two things that can go wrong:
The new thread might try to access the object before the constructor finishes initializing it. You can work around this by making sure all initialization is complete before you start the thread. But what if someone inherits from your class? You have no control over what their constructor will do.
What happens if your thread fails to start? There isn't really a clean way to handle errors in a constructor. You can throw an exception, but this is perilous since it means that your object's destructor will not get called. If you elect not to throw an exception, then you're stuck writing code in your various methods to check if things were initialized properly.
Generally speaking, if you have complex, error-prone initialization to perform, then it's best to do it in a method rather than the constructor.
Basically, what you need is two-phase construction: You want to start your thread only after the object is fully constructed. John Dibling answered a similar (not a duplicate) question yesterday exhaustively discussing two-phase construction. You might want to have a look at it.
Note, however, that this still leaves the problem that the thread might be started before a derived class' constructor is done. (Derived classes' constructors are called after those of their base classes.)
So in the end the safest thing is probably to manually start the thread:
class Thread {
public:
Thread();
virtual ~Thread();
void start();
// ...
};
class MyThread : public Thread {
public:
MyThread() : Thread() {}
// ...
};
void f()
{
MyThread thrd;
thrd.start();
// ...
}
It's fine, as long as you can start using that pointer right away. If you require the rest of the constructor to complete initialization before the new thread can use the pointer, then you need to do some synchronization.
Related
I have written up a framework for threaded objects with the following very basic structure:
class ThreadedObject {
public:
ThreadedObject(Thread* parentThread);
protected:
virtual void initialize();
}
class MyThreadedObject {
public:
MyThreadedObject(Thread* parentThread) : ThreadedObject(parentThread) {}
protected:
void initialize() override;
}
I have a mechanism whereby I don't call methods of subclasses of ThreadedObject's directly, instead I pass them onto a queue (via std::function) to be executed within the correct thread (parentThread).
I ran into an issue with the initialize method. The intent of this method is to act as a thread-conscious "constructor." What I mean is, since a ThreadedObject can be created in ANY thread, that means its constructor will run in the thread is was created in. However, I want the initialization (that would normally be in the constructor) to occur within the parent thread of the ThreadedObject instance.
The simplest solution to this problem would be:
Thread myThread();
MyThreadedObject myObject(&myThread);
invoke(&myObject, &MyThreadedObject::initialize);
Assuming the invoke method looks at what thread is assigned to myObject and queues a call to initialize within that thread.
However, I am wondering if there is any way to have this happen automatically AFTER the object has been constructed. My naive solution was to do the following:
ThreadedObject::ThreadedObject(Thread* parentThread) {
//...
invoke(this, &ThreadedObject::initialize);
}
However, I learned quickly that you can't call a virtual method like this from within the constructor of a base class.
It looks to me as if I need some way to call initialize AFTER all the layers of constructors (base -> child 1 -> child 2 -> ...) have completed.
Is something like this possible?
Thanks!
EDIT
I found an article about the same problem here: Is there any automated way to implement post-constructor and pre-destructor virtual method calls?
I am wondering if my real question then becomes, is there a way to wrap the construction of ThreadedObjects and their child classes in some sort of critical section so that construction completes before any other threads can take over?
I would like to use a class that manages a thread (or several threads). Using composition, this would look like:
class MyClass{
private:
std::thread mythread;
void _ThreadMain();
public:
MyClass();
// other fields
}
Because the default constructor for an std::thread is pointless, I would need to call it explicitly in MyClass constructor:
MyClass::MyClass() : mythread(&MyClass::_ThreadMain,this) {}
However, in this case the _ThreadMain method will be likely executed before MyClass is constructed, leading to any kind of weird behaviour. This is clearly unsafe. How can I fix this?
An obvious solution would be to use a pointer to std::thread instead, and add another member function:
void MyClass::Start(){
// This time mythread is of type std::thread*
mythread = new std::thread(&MyClass::_ThreadMain,this); // One could use std::unique_pointer instead.
}
which would fire up that thread. In this case it would be called after the class is constructed, which will be indeed safe.
However, I am wondering if there is any reasonable solution that would allow me not to use pointers for this. It feels like it should be possible somehow (hey, there must be a way to launch a thread when a class is constructed!), but I cannot come up with anything that would not cause troubles.
I have considered using a conditional variable so that the _ThreadMain waits till the constructor has done its work, but I cannot use one before the class is constructed, right? (This would also be unhelpful if MyClass was a derived class)
You can use a thread in combination with move semantics:
class MyClass final
{
private:
std::thread mythread;
void _ThreadMain();
public:
MyClass()
: mythread{} // default constructor
{
// move assignment
mythread = std::thread{&MyClass::_ThreadMain, this};
}
};
The move assignment operator is documented on the following page. In particular, it is noexcept and no new thread is created.
http://en.cppreference.com/w/cpp/thread/thread/operator%3D
There is no better way, in general, than having a separate Start function.
Suppose MyClass is a base class for some future (unknown) class Derived. If the thread is started while (or before) the MyClass constructor runs, it always risks calling the "wrong" implementation of some virtual function overridden by Derived.
The only way to avoid this is to have the thread wait until after Derived is fully constructed, and the only way to do that is to call some other function after the Derived constructor completes to tell the thread to "go"... Which means you must have some kind of separately-invoked Go function.
You might as well just have a separately-invoked Start function instead and forego the complexity of waiting.
[Update]
Note that, for complex classes, "Two-Phase Construction" is an idiom recommended by some. Starting the thread would fit seamlessly into the "initialization" phase.
Consider separating the task from the thread management and launching.
One class creates a runner and any synchronization primitives snd the like, The other handles launching it. This allows construction of the runnable to fail before threading starts.
It also means the runnable is fully constructed prior to it being run.
Now a first pass would have the runner be a std::thread, but some stuff helping with abort and cleanup and continuations can be useful.
The run object could be a simple callable, or could add extra supportmfor the runnable to interact with it.
I've already seen similar question: Destructor vs member function race
.. but didn't find the answer for the following. Suppose we have a class owning some worker thread. Destructor of the class can look like:
~OurClass
{
ask_the_thread_to_terminate;
wait_for_the_thread_to_terminate;
....
do_other_things;
}
The question is: may we call OurClass's member functions in the worker thread as we are sure all these calls will be done before do_other_things in the destructor?
Yes you can. Destruction of member variables willonly start after do_other_things completes its execution. It is safe to call member functions before object gets destructed.
Well, you kinda can do that, but it's easy to make a mistake this way. For example, if you do something like:
~OurClass
{
delete *memberPointer_;
ask_the_thread_to_terminate; // the thread calls OurClass::foo();
wait_for_the_thread_to_terminate;
....
do_other_things
}
void OurClass::foo()
{
memberPointer->doSomething();
}
you will be in trouble. It also makes it harder to read through the code. So you will have to be careful with the order of operations and stuff like that. In general if it's possible to change the architecture to avoid such complicated constructions, I would suggest to do it.
The implicit destruction of any data members occurs after execution of the last explicit line of your destructor, so all those data members are still fully functional whilst you wait for the thread. Hence, you must only avoid any premature explicit destruction of any data members (as exemplified in SingerOfTheFall's pathological code).
In Rastertek DirectX tutorials they have empty constructors and destructors and instead use initialize() and shutdown() functions for objects initialization and cleaning up. After using this design for a while I can somewhat understand the benefits of having an initialize() method, but I can't see how using a shutdown() method is any better than putting all the clean-up code in the destructor.
The reason they provide is the following:
You will also notice I don't do any object clean up in the class destructor. I instead do all my object clean up in the Shutdown function you will see further down. The reason being is that I don't trust it to be called. Certain windows functions like ExitThread() are known for not calling your class destructors resulting in memory leaks. You can of course call safer versions of these functions now but I'm just being careful when programming on windows.
So the general usage pattern looks like this:
class Renderer
{
public:
Renderer() { }
~Renderer() { }
bool initialize(...) { /* perform initialization */ }
void shutdown() { /* clean-up */ }
};
Renderer* renderer = new Renderer;
renderer->initialize(...);
// use the renderer
renderer->shutdown();
delete renderer;
renderer = NULL;
When looking at Rastertek's code it seems to me that they're coming from C background (initializing all variables at the top of the function, using only raw pointers and raw arrays etc.), so I wonder if this is yet another thing that is unnecessary in modern C++ (for one it makes it more difficult to use smart pointers). Is there any real benefit to this design?
Generally, it is a bad advice not to do a cleanup in the destructor.
But you can do it if the clean operation can fail, and you want to throw an exception. Then you have to be careful, as another exception would call abort(). For that particular case, doing cleanup in a separate function makes sense.
By the way, the code example indeed looks like from someone coming from the c world.
The reason being is that I don't trust it to be called. Certain windows functions like ExitThread() are known for not calling your class destructors resulting in memory leaks.
That is correct, but try to avoid such functions. Also from here :
There is no portable way in C++11 (that I'm aware of) to non-cooperatively kill a single thread in a multi-thread program (i.e. without killing all threads).
therefore just let the thread nicely finish, and destructors will be called.
I am not very good in multithreading programming so I would like to ask for some help/advice.
In my application I have two threads trying to access a shared object.
One can think about two tasks trying to call functions from within another object. For clarity I will show some parts of the program which may not be very relevant but hopefully can help to get my problem better.
Please take a look at the sample code below:
//DataLinkLayer.h
class DataLinkLayer: public iDataLinkLayer {
public:
DataLinkLayer(void);
~DataLinkLayer(void);
};
Where iDataLinkLayer is an interface (abstract class without any implementation) containing pure virtual functions and a reference (pointer) declaration to the isntance of DataLinkLayer object (dataLinkLayer).
// DataLinkLayer.cpp
#include "DataLinkLayer.h"
DataLinkLayer::DataLinkLayer(void) {
/* In reality task constructors takes bunch of other parameters
but they are not relevant (I believe) at this stage. */
dll_task_1* task1 = new dll_task_1(this);
dll_task_2* task2 = new dll_task_2(this);
/* Start multithreading */
task1->start(); // task1 extends thread class
task2->start(); // task2 also extends thread class
}
/* sample stub functions for testing */
void DataLinkLayer::from_task_1() {
printf("Test data Task 1");
}
void DataLinkLayer::from_task_2() {
printf("Test data Task 2");
}
Implementation of task 1 is below. The dataLinLayer interface (iDataLinkLayer) pointer is passed to the class cosntructor in order to be able to access necessary functions from within the dataLinkLayer isntance.
//data_task_1.cpp
#include "iDataLinkLayer.h" // interface to DataLinkLayer
#include "data_task_1.h"
dll_task_1::dll_task_1(iDataLinkLayer* pDataLinkLayer) {
this->dataLinkLayer = pDataLinkLayer; // dataLinkLayer declared in dll_task_1.h
}
// Run method - executes the thread
void dll_task_1::run() {
// program reaches this point and prints the stuff
this->datalinkLayer->from_task_1();
}
// more stuff following - not relevant to the problem
...
And task 2 looks simialrly:
//data_task_2.cpp
#include "iDataLinkLayer.h" // interface to DataLinkLayer
#include "data_task_2.h"
dll_task_2::dll_task_2(iDataLinkLayer* pDataLinkLayer){
this->dataLinkLayer = pDataLinkLayer; // dataLinkLayer declared in dll_task_2.h
}
// // Run method - executes the thread
void dll_task_2::run() {
// ERROR: 'Access violation reading location 0xcdcdcdd9' is signalled at this point
this->datalinkLayer->from_task_2();
}
// more stuff following - not relevant to the problem
...
So as I understand correctly I access the shared pointer from two different threads (tasks) and it is not allowed.
Frankly I thought that I will be able to access the object nevertheless however the results might be unexpected.
It seems that something goes terribly wrong at the point when dll_task_2 tries to call the function using pointer to the DataLinkLayer. dll_task_2 has lower priority hence it is started afterwards. I don't understand why i still cannot at least access the object...
I can use the mutex to lock the variable but I thought that the primary reason for this is to protect the variable/object.
I am using Microsoft Visual C++ 2010 Express.
I don't know much about multithreading so maybe you can suggest a better solution to this problem as well as explain the reason of the problem.
The address of the access violation is a very small positive offset from 0xcdcdcdcd
Wikipedia says:
CDCDCDCD Used by Microsoft's C++ debugging runtime library to mark uninitialised heap memory
Here is the relevant MSDN page.
The corresponding value after free is 0xdddddddd, so it's likely to be incomplete initialization rather than use-after-free.
EDIT: James asked how optimization could mess up virtual function calls. Basically, it's because the currently standardized C++ memory model makes no guarantees about threading. The C++ standard defines that virtual calls made from within a constructor will use the declaring type of the constructor currently being run, not the final dynamic type of the object. So this means that, from the perspective of the C++ sequential execution memory model, the virtual call mechanism (practically speaking, a v-table pointer) must be set up before the constructor starts running (I believe the specific point is after base subobject construction in the ctor-initializer-list and before member subobject construction).
Now, two things can happen to make the observable behavior different in a threaded scenario:
First, the compiler is free to perform any optimization that would, in the C++ sequential execution model, act as-if the rules were being followed. For example, if the compiler can prove that no virtual calls are made inside the constructor, it could wait and set the v-table pointer at the end of the constructor body instead of the beginning. If the constructor doesn't give out the this pointer, since the caller of the constructor also hasn't received its copy of the pointer yet, then none of the functions called by the constructor can call back (virtually or statically) to the object under construction. But the constructor DOES give away the this pointer.
We have to look closer. If the function to which the this pointer is given is visible to the compiler (i.e. included in the current compilation unit), the the compiler can include its behavior in the analysis. We weren't given that function in this question (the constructor and member functions of class task), but it seems likely that the only thing that happens is that said pointer is stored in a subobject which is also not reachable from outside the constructor.
"Foul!", you cry, "I passed the address of that task subobject to a library CreateThread function, therefore it is reachable and through it, the main object is reachable." Ah, but you do not comprehend the mysteries of the "strict aliasing rules". That library function does not accept a parameter of type task *, now does it? And being a parameter whose type is perhaps intptr_t, but definitely neither task * nor char *, the compiler is permitted to assume, for purposes of as-if optimization, that it does not point to a task object (even if it clearly does). And if it does not point to a task object, and the only place our this pointer got stored is in a task member subobject, then it cannot be used to make virtual calls to this, so the compiler may legitimately delay setting up the virtual call mechanism.
But that's not all. Even if the compiler does set up the virtual call mechanism on schedule, the CPU memory model only guarantees that the change is visible to the current CPU core. Writes may become visible to other CPU cores in a completely different order. Now, the library create thread function ought to introduce a memory barrier that constrains CPU write reordering, but that fact that Koz's answer introducing a critical section (which definitely includes a memory barrier) changes the behavior suggests that perhaps no memory barrier was present in the original code.
And, CPU write reordering can not only delay the v-table pointer, but the storage of the this pointer into the task subobject.
I hope you have enjoyed this guided tour of one small corner of the cave of "multithreaded programming is hard".
printf is not, afaik, thread safe. Try surrounding the printf with a critical section.
To do this you InitializeCriticalSection inside iDataLinkLayer class. Then around the printfs you need an EnterCriticalSection and a LeaveCriticalSection. This will prevent both functions entering the printf simultaneously.
Edit: Try changing this code:
dll_task_1* task1 = new task(this);
dll_task_2* task2 = new task(this);
to
dll_task_1* task1 = new dll_task_1(this);
dll_task_2* task2 = new dll_task_2(this);
Im guessing that task is in fact the base class of dll_task_1 and dll_task_2 ... so, more than anything, im surprised it compiles ....
I think it's not always safe to use 'this' (i.e. to call a member function) before the end of the constructor. It could be that task are calling member function of DataLinkLayer before the end of DataLinkLayer constructor. Especially if this member function is virtual:
http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.7
I wanted to comment on the creation of the DataLinkLayer.
When I call the DataLinkLayer constructor from main:
int main () {
DataLinkLayer* dataLinkLayer = new DataLinkLayer();
while(true); // to keep the main thread running
}
I, of coruse, do not destruct the object, this is first. Now, inside the DataLinkLayer cosntructor I initialize many (not only these two tasks) other objects isntances and pass to most of them dataLinkLayer pointer (using this). This is legal, as far as I am concerned. Put it further - it compiles and runs as expected.
What I became curious about is the overall design idea that I am following (if any :) ).
The DataLinkLayer is a parent class that is accessed by several tasks which try to modify it parameters or perform some other processing. Since I want that everything remain as decoupled as possible I provide only interfaces for the accessors and encapsulate the data so that I don't have any global variables, friend functions etc.
It would have been a pretty easy task to do if only multithreading would not be there. I beleive I will encounter many other pitfalls on my way.
Feel free to discuss it please and merci for your generous comments!
UPD:
Speaking of passing the iDataLinkLayer interface pointer to the tasks - is this a good way to do it? In Java it would be pretty usual thing to realize a containment or so called strategy pattern to make things decoupled and stuff. However I am not 100% sure whether it is a good solution in c++... Any suggestions/commnets on it?