From: Jonathan Wakely <jwakely@redhat.com>
To: Maged Michael <maged.michael@gmail.com>
Cc: libstdc++@gcc.gnu.org
Subject: Re: Proposed patch to skip the last atomic decrements in _Sp_counted_base::_M_release
Date: Mon, 7 Dec 2020 15:57:08 +0000 [thread overview]
Message-ID: <20201207155708.GG2309743@redhat.com> (raw)
In-Reply-To: <CABBFi0_QAQHCymK=APvoeOoCeTaSDHh=uLVFyWgko=+EyuZokw@mail.gmail.com>
On 07/12/20 07:30 -0500, Maged Michael via Libstdc++ wrote:
> void
> _M_release() noexcept
>+ {
>+ if (!__LP64__ || sizeof(_Atomic_word) != 4 || sizeof(long long) !=
>8)
>+ {
>+ _M_release_orig();
>+ return;
>+ }
>+ _GLIBCXX_SYNCHRONIZATION_HAPPENS_BEFORE(&_M_use_count);
>+ _GLIBCXX_SYNCHRONIZATION_HAPPENS_BEFORE(&_M_weak_count);
>+ if ((__atomic_load_n((long long*)(&_M_use_count), __ATOMIC_ACQUIRE)
>+ == 0x100000001))
>+ {
I think we want a comment here explaining what it's doing:
// Both counts are 1, so there are no weak references and
// we are releasing the last strong reference. No other
// threads can observe the effects of this _M_release()
// call (e.g. calling use_count()) without a data race.
>+ _GLIBCXX_SYNCHRONIZATION_HAPPENS_AFTER(&_M_use_count);
>+ _GLIBCXX_SYNCHRONIZATION_HAPPENS_AFTER(&_M_weak_count);
>+ _M_dispose();
_M_dispose() will run the destructor for the owned object. If that
object has a reference to the shared_ptr then it can call use_count()
on it. That isn't a data race, because it's within the same thread.
Previously the object's destructor would have observed that the use
count had dropped to zero. In this new implementation, the use count
is still 1 when the object is destroyed.
Similarly, the object's destructor could create a new weak_ptr from
*this. Previously that would see that the use count is zero, and so
fail. With the new code it would succeed, and increase the weak count,
and be left with a dangling pointer after the destroy here:
>+ _M_destroy();
I think to avoid these problems you need to set both counts to 0
before calling _M_dispose(). Those can be simple non-atomic writes
though, since we know that only the current thread can observe those
values without data races.
next prev parent reply other threads:[~2020-12-07 15:57 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-12-07 12:30 Maged Michael
2020-12-07 15:57 ` Jonathan Wakely [this message]
2020-12-07 16:23 ` Jonathan Wakely
-- strict thread matches above, loose matches on Subject: below --
2020-12-07 12:24 Maged Michael
2020-12-07 15:28 ` Marc Glisse
2020-12-07 15:41 ` Jonathan Wakely
2020-12-08 4:10 ` Maged Michael
2020-12-08 8:01 ` Marc Glisse
2020-12-08 9:56 ` Jonathan Wakely
2020-12-07 15:37 ` Jonathan Wakely
2020-12-08 4:06 ` Maged Michael
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20201207155708.GG2309743@redhat.com \
--to=jwakely@redhat.com \
--cc=libstdc++@gcc.gnu.org \
--cc=maged.michael@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).