Dear C++ Standards People,
I just wanted to check a situation with you, about what the various standards say, if anything, about a threading situation I've come across recently.
- C++11 with VC14
- Using std::threads in a threadpool type application.
- Works perfectly within GoogleTest but when loaded from a DLL in a application, it hangs.
Debugged it and the fact is that the 'this' pointer changes in between times when the threads are created and when the main loop is running. The this pointer that the threads have end up pointing to garbage (so it's not a stale copy of the class). If I query the this pointer value in the main thread it is different to the one the threads have. I think the class instance has been relocated in memory. Nothing in my code is copying the class - it is effectively a singleton.
It's something like this:
for (size_t i=0; i < numThreads; ++) {
threadPool_.push_back(std::thread(&ClassName::ClassFn, this, arg1, arg2, arg3));
}
. . .
queue work
. . .
condition_variable stuff
threadPool_ is a private member of ClassName and of type std::vector<std::thread>
I checked the C+11 standard Section 30 and I didn't see this situation covered - in fact the work relocation doesn't seem to appear in the document at all. Maybe I'm barking up the wrong tree here. From what I've gathered the constructor to std::thread can take a std::invoke pattern which I believe I'm following above. However in a lot of examples I can find the instance variable passed in is a stack variable not this, perhaps this is special? Also std::invoke is C++17 and beyond so that's maybe not applicable to C++11's std::thread?
Hopefully I'm doing something dumb and this can be fixed with a reference wrapper or somehting like this. I can ask a wider audience about this situation but I wanted to check in with someone who knows the threading standards to check that I haven't made a silly mistake first. The fact that it compiles cleanly and runs ok without relocations in a test harness gives me encouragement that the code is OK.
I know the standard can't cover all the implementation details, and it's always possible to write pathological code which will always break, but something like this seems pretty fundamental, providing I'm not breaking the standard here?
Thank you,
David.
--
Mathematics, Modelling, C/C++, Python, Linux, SQL, MATLAB, Mathematica.