Skip to content
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

weak_ptr conversions can sometimes avoid locking #2282

Merged
merged 28 commits into from
Nov 3, 2021

Conversation

AlexGuteniev
Copy link
Contributor

Resolves #258

Test happen to recreate the issue for me on attempt #0
if unconditionally avoid locking

Resolves microsoft#258

Test happen to recreate the issue for me on attempt #0
if unconditionally avoid locking
@AlexGuteniev AlexGuteniev requested a review from a team as a code owner October 17, 2021 18:22
@CaseyCarter CaseyCarter added the performance Must go faster label Oct 17, 2021
rather than C-style casts
because we don't need to punch through accessibility
stl/inc/memory Outdated Show resolved Hide resolved
@CaseyCarter CaseyCarter self-assigned this Oct 20, 2021
@StephanTLavavej StephanTLavavej changed the title Sometimes avoid locking weak_ptr conversions can sometimes avoid locking Oct 20, 2021
@cpplearner
Copy link
Contributor

IIUC this does not optimize for the X -> const X case mentioned in #258 (since static_cast<X*>(declval<const X*>()) is invalid). Maybe also consider is_convertible<_Ty2(*)[], _Ty(*)[]>?

@AlexGuteniev
Copy link
Contributor Author

IIUC this does not optimize for the X -> const X case mentioned in #258 (since static_cast<X*>(declval<const X*>()) is invalid). Maybe also consider is_convertible<_Ty2(*)[], _Ty(*)[]>?

Good point, but I preferred to update the existing check to cover Derived -> const Base as well

stl/inc/memory Outdated Show resolved Hide resolved
@StephanTLavavej
Copy link
Member

@cpplearner I think that @AlexGuteniev's code does handle X -> const X, although (as I mentioned in my review) the logic is very subtle.

Suppose that we're constructing a weak_ptr<const int> from weak_ptr<int>. The constructor is weak_ptr(const weak_ptr<_Ty2>& _Other), so "our" _Ty is const int and "their" _Ty2 is int. The type trait's static_cast is intentionally reversed:

template <class _Ty2>
static constexpr bool _Is_virtual_base_cast<_Ty2, decltype(static_cast<const _Ty2*>(_STD declval<_Ty*>()))> = false;

This starts with declval<_Ty*>(), i.e. declval<const int*>(), and asks whether we can static_cast<const _Ty2*>, i.e. static_cast<const int*>. So we've formed the same type, the static_cast is well-formed, and the type trait returns false (saying "we don't need the expensive machinery to avoid virtual inheritance weirdness").

At a high level, the technique is saying that when implicitly converting from source-to-dest (whether adding constness or converting derived-to-base), a static_cast from dest-to-const source is valid except in the virtual inheritance case we care about.

(Aside: I noticed that this doesn't consider volatile and I'm fine with that, it'll select the slow path.)

@AlexGuteniev
Copy link
Contributor Author

For the record, @cpplearner comment was useful, as I added const after it

@StephanTLavavej
Copy link
Member

Thanks for finding the EDG bug! I reported it as DevCom-1564433 and pushed a perma-workaround after discovering that changing _STD declval<_Ty*>() to static_cast<_Ty*>(nullptr) avoids the bug.

As we don't need to skip EDG here
@CaseyCarter CaseyCarter removed their assignment Oct 27, 2021
@StephanTLavavej StephanTLavavej self-assigned this Nov 2, 2021
@StephanTLavavej
Copy link
Member

I'm mirroring this to the MSVC-internal repo - please notify me if any further changes are pushed.

@StephanTLavavej
Copy link
Member

@AlexGuteniev @CaseyCarter I've pushed changes to fix test failures for /clr:pure, the Betrayer of Hope - the simplest thing is to entirely disable this optimization.

@CaseyCarter
Copy link
Member

@AlexGuteniev @CaseyCarter I've pushed changes to fix test failures for /clr:pure, the Betrayer of Hope - the simplest thing is to entirely disable this optimization.

Having recently begun my fourth trip through the Wheel of Time, I'm deeply offended that you would liken /clr:pure to Ishamael. Not even one of the Forsaken is as dark and twisted as /clr:pure!

@StephanTLavavej StephanTLavavej merged commit 3279b7c into microsoft:main Nov 3, 2021
@StephanTLavavej
Copy link
Member

Thanks for implementing this long-dreamed-of optimization! 🐈 💤 😻

@AlexGuteniev AlexGuteniev deleted the sometimes_avoid_locking branch November 3, 2021 05:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
performance Must go faster
Projects
None yet
Development

Successfully merging this pull request may close these issues.

<memory>: weak_ptr's converting constructors could sometimes avoid locking
5 participants