-
Notifications
You must be signed in to change notification settings - Fork 544
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Disable trivially_constructible test for atomic on MSVC++. #654
Conversation
MSVC++ implements P0883 unconditionally, which changes the rules for std::atomic. It removes atomic's trivial constructor, and makes the default constructor value initialize the T. Note that Mongo was not following the C++11 rules, because it used the atomic before calling atomic_init first. MSVC++ never implemented the C++11 rules and previously default initialized the T. All versions of MSVC++ will provide constant initialization of the guarded value "current_instance". In old versions, atomic didn't implement P0883 due to bugs in the constexpr evaluator; in current versions the constexpr evaluator was fixed and atomic value initializes unconditionally. Therefore, this PR disables the check whenever MSVC++'s standard library is detected. See microsoft/STL#661 for further discussion.
Previously submitted as mongodb/mongo-cxx-driver#654
@BillyONeal - I find the following language in the documentation for
The atomic is being constructed with an argument, so I think we are invoking one of its non-default constructors. Or perhaps we have fallen into one of the traps that motivated P0883? Are we actually violating the rules? Could you clarify? Regarding the removal of the |
Good point. But if that's true, the trivial constructability static assert doesn't mean anything, since you're not engaging the trivial ctor even if it were trivial. So maybe the right fix is to delete it outright? |
Maybe; I'm ill equipped to make global assumptions about the code in question. |
@BillyONeal - Yup, I started this. As I noted, I don't work actively on this project right now, though others do, and it has been quite a few years since I wrote that. I will need to go do some digging to uncover the reasoning behind the code. I remember that we spent considerable time evaluating solutions and that we felt we were in the right with out decision, but of course we may have got it wrong! |
The comment on the commit indicates that it's intending to avoid a dynamic initializer (presumably to avoid the 'static initialization order fiasco') which would make sense given that it's asserting triviality. Unfortunately both I and the original commit didn't pay attention that the default ctor isn't being used here so old versions of VC would give you a dynamic initializer anyway. |
Previously submitted as mongodb/mongo-cxx-driver#654
So should I remove this line in v3.5 or change decltype(current_instance) to v_noabi::instance *? |
@BillyONeal - Sorry for the delay. I did some archaeology on this. The relevant background is in:
It appears that the code has evolved since then, notably I think the ability to recreate the instance was removed as part of https://jira.mongodb.org/browse/CXX-1300, since the underlying C driver couldn't faithfully support it. The idea in #513 was indeed to avoid a dynamic initializer, by ensuring that The intention of the Given that I spend a lot less time on the details of C++ these days, can you clarify for me a few things?
|
Yes, but lots of compilers (e.g. VS2019 before 16.6) were buggy about it.
Since you're using the constructor that initializes the contained value, I don't believe so. If you were default initializing it you would have needed to call
I don't believe there are any assertions you can write. Note that the existing assertion does not actually assert anything about current_instance. |
Sure, but it asserts something about the type of current instance. However, that assertion is also irrelevant since we are using the value-taking constructor per prior discussion. Given all this, and your other answers above, my recommendation would be to update this PR to unconditionally remove the trivially_constructible test on all platforms, and then I'll be happy to get this merged. |
Done. |
@BillyONeal - LGTM, thank you for being patient while I sorted through the history. @kevinAlbs, I think this should get merged, but probably by one of the active C++ driver developers. |
These changes LGTM, with P0883 that static_assert is not useful and I think it's a good idea to get rid of it. But, @BillyONeal can you explain in more detail why we expect constant initialization for current_instance? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM. Thank you @BillyONeal for the contribution and explanation, and to @acm for the background. It seems reasonable to remove this assertion if we were not invoking the default constructor.
Because it's calling a constexpr constructor. Note that on Visual Studio before 2019 version 16.6, it is not getting constant initialization. |
Merging, thanks again @BillyONeal! |
MSVC++ implements P0883 unconditionally, which changes the rules for std::atomic. It removes atomic's trivial constructor, and makes the default constructor value initialize the T.
Note that Mongo was not following the C++11 rules, because it used the atomic before calling atomic_init first. MSVC++ never implemented the C++11 rules and previously default initialized the T.
All versions of MSVC++ will provide constant initialization of the guarded value "current_instance". In old versions, atomic didn't implement P0883 due to bugs in the constexpr evaluator; in current versions the constexpr evaluator was fixed and atomic value initializes unconditionally. Therefore, this PR disables the check whenever MSVC++'s standard library is detected.
See microsoft/STL#661 for further discussion.