An Issue I Wish To Raise Awareness On
via Digitalmars-d
digitalmars-d at puremagic.com
Wed Jul 19 14:50:32 PDT 2017
On Wednesday, 19 July 2017 at 20:59:03 UTC, Atila Neves wrote:
> On Wednesday, 19 July 2017 at 20:23:18 UTC, Jonathan M Davis
> wrote:
>> On Wednesday, July 19, 2017 2:29:04 PM MDT Atila Neves via
>> Digitalmars-d wrote:
>>> On Tuesday, 18 July 2017 at 19:24:18 UTC, Jonathan M Davis
>>> wrote:
>>> > On Tuesday, July 18, 2017 18:06:56 Atila Neves via
>>> >> Except for a programmer explicitly and manually calling
>>> >> the destructor (in which case, don't), the destructor is
>>> >> only ever called by one thread.
>>> >
>>> > It could still be a problem if the struct has a member
>>> > variable that is a reference type, because then something
>>> > else could refer to that object, and if it's shared, then
>>> > you would need to protect it, and the operations that
>>> > shared prevents should still be prevented. For full-on
>>> > value types, it should be a non-issue though.
>>> >
>>> > - Jonathan M Davis
>>>
>>> Mmm, I guess so. As Marco pointed out, it's a similar problem
>>> with immutable (because the compiler casts it away before
>>> calling the destructor).
>>>
>>> Although I dare say that anybody writing code that depends on
>>> such locking and destruction when shared is unlikely to get
>>> it right in the first place.
>>
>> Well, consider that something like a reference counted type
>> would have to get this right. Now, a reference counted type
>> that worled with shared would need to be written that way -
>> simply slapping shared on such a smart pointer type isn't
>> going to work - but it would then be really bad for the
>> destructor to be treated as thread-local.
>
> Not necessarily - the reference counted smart pointer doesn't
> have to be `shared` itself to have a `shared` payload.
Agreed. I'm exploring doing the same for std.stdio.File.
> I'm not even entirely sure what the advantage of it being
> `shared` would be, or even what that would really mean.
>
There are plenty of cases where you need the smart pointer to be
shared itself -
e.g. member composition and global variables. See also: [0]
Note that this doesn't play well with regular [1] value types
becuase e.g. you don't have control over the synthesized bit-blit
for this(this) and so you can't assume that structs with a single
pointer member are updated atomically, even if would write the
opAssign that way. In C++17 atomic_shared_ptr has it's
copy-constructor and assign operator deleted. You can only do
atomic<T> like ops with it and derive a plain shared_ptr<T> from
it, kind-of like core.atomic's HeadUnshared(T).
[0]:
https://www.justsoftwaresolutions.co.uk/threading/why-do-we-need-atomic_shared_ptr.html
[1]: http://stepanovpapers.com/DeSt98.pdf (definition of regular
types).
More information about the Digitalmars-d
mailing list