Date: Fri, 12 Aug 2022 17:24:34 +0100
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.
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. LinkedIn Profile: https://www.linkedin.com/in/david-carter-a259671a4/
Received on 2022-08-12 16:24:46