-
Notifications
You must be signed in to change notification settings - Fork 1.5k
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
mutex.cpp
, cond.cpp
: Use static dispatch
#3770
Conversation
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
…iable`. We never provided user-visible declarations for what they returned. It's extremely unlikely that users were successfully calling them in any useful way, so the bincompat risk of nulling out the vptrs is minimal. I am opting to `=delete` these functions, instead of simply not declaring them, so that attempted calls will have a slightly more comprehensible error message. As the TRANSITION comments note, in theory we could provide implementations that return the underlying Win32 machinery which actually would be possible to document. I am also changing `condition_variable`'s `native_handle_type` from `_Cnd_t` (an alias provided by `<xthreads.h>` for `_Cnd_internal_imp_t*`, which is forward-declared and never defined for users) to `void*` and grouping it with the function, which follows the Standard's order.
stl/inc/mutex
Outdated
@@ -95,9 +95,8 @@ public: | |||
|
|||
using native_handle_type = void*; |
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.
Should we still declare the native_handle_type
even if native_handle
is not usable? I guess this is technically conforming, but looks weird.
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.
Yeah, it's an open question.
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.
[thread.req.native]/1:
Several classes described in this Clause have members
native_handle_type
andnative_handle
. The presence of these members and their semantics is implementation-defined."
We can do whatever we like here, if we document it. I'd prefer for native_handle_type
to be undefined or denote void
, but we can debate it after merging this change.
Whatever we do, we need to update https://learn.microsoft.com/en-us/cpp/standard-library/mutex-class-stl?view=msvc-170#native_handle.
I don't see it. (I previously attempted a PR with fake vtable instead, that was rejected) |
Yes, new code will not work with old DLL/LIB, but IIUC that's unsupported anyway. |
I believe it is unsupported for the LIB, but for the DLL it is supported due to "printer driver problem" |
@AlexGuteniev makes a very good point. If we're working towards |
Let's work towards this then! And then we won't even need manual devirtualization as in this PR: due to |
Oh, forgot about [thread.mutex.class]/3:
It can't be made |
ah. That is unfortunate. edit: given that we never call |
Actually, I believe I have convinced myself that we don't even need to retain the I was led to this by thinking about whether To repeat/clarify, because ABI issues are unfamiliar to reason about, there is only one copy of the STL's DLL or static LIB that we ever need to worry about. (It is possible for multiple user DLLs to be loaded into a single process with separate STL DLLs or statically linked LIBs, but they cannot communicate CRT/STL objects between themselves.) So, the STL's DLL/LIB is always internally consistent and we don't need to worry about mix-and-match the way that we do for headers built by users. The flat C API (with the I will push a change. If anyone believes that my analysis is incorrect, I welcome corrections, but please check with me before beginning an "edit war" of commits. 😺 |
One more thought: for a |
If we don't call the constructor from DLL, and don't initialize vtable by other means, I'm afraid "print driver" scenario would be observable by crash on trying to lock the mutex. |
My understanding that escape hatch is not good here, unlike, say, atomic alignment escape hatch. |
This reverts commit 34fdc17.
I've pushed a revert, to restore the null vptrs (in advance of the weekly maintainer meeting). @strega-nil-ms noted that a guaranteed crash was safer and better than treating data as a vptr. We will still need to talk about the print driver scenario for a followup |
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.
From Discord discussion, STL plans to address my comments, so I'll go ahead and approve.
stl/inc/mutex
Outdated
@@ -95,9 +95,8 @@ public: | |||
|
|||
using native_handle_type = void*; |
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.
[thread.req.native]/1:
Several classes described in this Clause have members
native_handle_type
andnative_handle
. The presence of these members and their semantics is implementation-defined."
We can do whatever we like here, if we document it. I'd prefer for native_handle_type
to be undefined or denote void
, but we can debate it after merging this change.
Whatever we do, we need to update https://learn.microsoft.com/en-us/cpp/standard-library/mutex-class-stl?view=msvc-170#native_handle.
I'm mirroring this to the MSVC-internal repo - please notify me if any further changes are pushed. |
Thanks for this major and long-awaited simplification! 🎉 😻 ✨ |
By simply removing `~_Mutex_base`. This destructor has been only a debug check since microsoftGH-3770. Losing the debug check is a small price to pay to elide the destructor call, doubly so for static storage duration mutexes that now won't need dynamic initializers to register with `at_exit`. `_Mtx_destroy` and `_Mtx_destroy_in_situ` are only called by APIs preserved for binary compatibility, so mark them as also "preserved for binary compatibility".
After #2317 removed
stl_critical_section_vista
andstl_condition_variable_vista
, only the Win7 versions inherit from the corresponding interfaces. Thus the functions inmutex.cpp
andcond.cpp
could directly use the Win7 classes, without going through the interfaces. This improves performance, and makes it easier to implementconstexpr mutex
.The first commit (24922f3) changes the getters in
_Mtx_internal_imp_t
and_Cnd_internal_imp_t
to return the Win7 classes. Since these classes arefinal
, apparently the compiler knows to use static dispatch for them.Subsequent commits change
create_stl_critical_section
andcreate_stl_condition_variable
to create non-polymorphic classes, with the "vptr" set to nullptr.I can imagine that these cause trouble if a
mutex
object is created by new code and used by old code, and old code uses the old function definitions (because it links to an old static lib?). IIUC this scenario is unsupported, and it will be a noticeable breakage due to null dereference.