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