Hi again Charles,
While I'm at it... I've seen that some time ago you've changed some of the constant-meant methods in your C++ code to use that local, "static const" technique (eg. for Geodesic::WGS84()). While I was originally quite found of this kind of stuff, and this works perfectly well in a single-threaded environment, there are some issues using this coding hack in a multi-threaded environment.
Unfortunately this is a real issue : I've had to revert to another way to initialize those things in my code : since using VS "unit test" cpp framework (which appears multi-threaded) i've even had cases where Math::pi() raised an access violation... I could be wrong, but this indeed seems tied to that static const technique : Reverting to good'old (ugly) macros for PI has solved the issue for me.
I'm afraid there's no "great" way to solve the static initialization problem (you came to this solution trying to avoid static initialization-order issues, I believe). I've read maybe a full-fledged C++11 compiler would handle this graciously with fences, or maybe GCC is more clever than VS in that regard, but in the meantime... there seem to be no other choice than macros for 'const double', and a cumbersome (but robust) application-wise GeographicLib::init() method for more advanced stuff like the default wgs84 ellipsoid (or even your multi-precision evaluation of pi).
Regards,
Guillaume Mirey [Now logged in after posting about inverting the lambda integral]
Last edit: FaleneLogics 2017-07-27
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
As far as I can tell C++11 mandates correct initialization of static
local objects even in multithreaded applications.
Is this consistent with your experience with Visual Studio? I.e., do
you run into problems with recent (2015 and 2017) versions of Visual
Studio? If so, can you provide sample code illustrating the problem?
Tentatively, I plan to retain the current idiom and to document the
potential problem with multithreaded applications in C++03 and suggest
the workaround of invoking the problem constant methods before the
multithreaed portion of the code is entered. (In any case, we are close
to the point where we can assume that all C++ compilers support C++11.)
Does the VS unit test framework allow you to specify code which is run
before the tests? If it does, you could test this advice with non C++11
versions of Visual Studio.
By the way, rather than using a macro for const double constants, just
remove the "static" from the declaration of the local variable. g++
(and probably Visual Studio) with any reasonable level of optimization
will evaluate atan2(0.0, -1.0) at compile time.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
C++11 standard enforcing this case to be handled gracefully, even in a multithreaded environment is indeed consistent with what I've read. As to whether it is indeed currently handled well, I would assume that any recent C++ compiler having undergone the C++11 switch has by now those functionnalities covered, but past years waiting for C++11 features to be implemented made me a little paranoid about my own assumptions on those matters. That being said, I do not claim that VS2015 or 17 would fail on this, surely they got the job done, and you're totally allowed to assume that your user base uses decent compilers by now.
Unfortunately this wasn't my case for my purposes (VS2012 as "minimum" target), and I'm in the process of trying to get all those things working and well covered by unit tests, so I don't have quite the time to perform multiplatform tests right now (besides, any "no-failure" would not prove much... the access violation which I mention in the OP occured sometimes after many, many runs).
You're right about CppUnitTestFramework allowing to fire code before launch, although I'm not sure I wasn't in one of such blocks initially, and not sure other threads were not already created by the framework. Hmm... interesting solution however to fire those accessors "by hand". Provided the calling code don't get optimized out by doing nothing of the results, but this could maybe get fixed with a volatile or something.
But I'm trying to recall the exact setting of the problem... possibly I did some nasty stuff myself with global (meh) variables accessing Math::pi(). If so, code to launch "before tests" would not be the end of it... I'm afraid this happened to me some weeks ago and by now I did change those static const (as well as worked on the original calling code all over the place). As for sample code... if by any chance I put my hands on some backup source from before the fix, I'll try to share.
Regards,
Guillaume Mirey
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Hi again Charles,
While I'm at it... I've seen that some time ago you've changed some of the constant-meant methods in your C++ code to use that local, "static const" technique (eg. for Geodesic::WGS84()). While I was originally quite found of this kind of stuff, and this works perfectly well in a single-threaded environment, there are some issues using this coding hack in a multi-threaded environment.
Unfortunately this is a real issue : I've had to revert to another way to initialize those things in my code : since using VS "unit test" cpp framework (which appears multi-threaded) i've even had cases where Math::pi() raised an access violation... I could be wrong, but this indeed seems tied to that static const technique : Reverting to good'old (ugly) macros for PI has solved the issue for me.
I'm afraid there's no "great" way to solve the static initialization problem (you came to this solution trying to avoid static initialization-order issues, I believe). I've read maybe a full-fledged C++11 compiler would handle this graciously with fences, or maybe GCC is more clever than VS in that regard, but in the meantime... there seem to be no other choice than macros for 'const double', and a cumbersome (but robust) application-wise GeographicLib::init() method for more advanced stuff like the default wgs84 ellipsoid (or even your multi-precision evaluation of pi).
Regards,
Guillaume Mirey
[Now logged in after posting about inverting the lambda integral]
Last edit: FaleneLogics 2017-07-27
As far as I can tell C++11 mandates correct initialization of static
local objects even in multithreaded applications.
Is this consistent with your experience with Visual Studio? I.e., do
you run into problems with recent (2015 and 2017) versions of Visual
Studio? If so, can you provide sample code illustrating the problem?
Tentatively, I plan to retain the current idiom and to document the
potential problem with multithreaded applications in C++03 and suggest
the workaround of invoking the problem constant methods before the
multithreaed portion of the code is entered. (In any case, we are close
to the point where we can assume that all C++ compilers support C++11.)
Does the VS unit test framework allow you to specify code which is run
before the tests? If it does, you could test this advice with non C++11
versions of Visual Studio.
By the way, rather than using a macro for const double constants, just
remove the "static" from the declaration of the local variable. g++
(and probably Visual Studio) with any reasonable level of optimization
will evaluate atan2(0.0, -1.0) at compile time.
C++11 standard enforcing this case to be handled gracefully, even in a multithreaded environment is indeed consistent with what I've read. As to whether it is indeed currently handled well, I would assume that any recent C++ compiler having undergone the C++11 switch has by now those functionnalities covered, but past years waiting for C++11 features to be implemented made me a little paranoid about my own assumptions on those matters. That being said, I do not claim that VS2015 or 17 would fail on this, surely they got the job done, and you're totally allowed to assume that your user base uses decent compilers by now.
Unfortunately this wasn't my case for my purposes (VS2012 as "minimum" target), and I'm in the process of trying to get all those things working and well covered by unit tests, so I don't have quite the time to perform multiplatform tests right now (besides, any "no-failure" would not prove much... the access violation which I mention in the OP occured sometimes after many, many runs).
You're right about CppUnitTestFramework allowing to fire code before launch, although I'm not sure I wasn't in one of such blocks initially, and not sure other threads were not already created by the framework. Hmm... interesting solution however to fire those accessors "by hand". Provided the calling code don't get optimized out by doing nothing of the results, but this could maybe get fixed with a volatile or something.
But I'm trying to recall the exact setting of the problem... possibly I did some nasty stuff myself with global (meh) variables accessing Math::pi(). If so, code to launch "before tests" would not be the end of it... I'm afraid this happened to me some weeks ago and by now I did change those static const (as well as worked on the original calling code all over the place). As for sample code... if by any chance I put my hands on some backup source from before the fix, I'll try to share.
Regards,
Guillaume Mirey