October 10, 2013
On 6/28/2013 6:42 PM, Michel Fortin wrote:
> Le 28-juin-2013 à 17:03, Rainer Schuetze <r.sagitario@gmx.de> a écrit :
>
>> Any parameter of type C is also lowered to shared_ptr!C.
> class C {}
>
> People still constantly forget that C used as a type represents a *reference* to an object of class C, not the object itself. If you replace type C with shared_ptr!C, you must then replace it with shared_ptr!(shared_ptr!C) and so on; there's no end to it.
>
> Also, I strongly doubt the compiler will be able to elide redundant calls to retain/release made within shared_ptr!C while still respecting normal struct semantics.
>

Using some sort of shared_ptr!T was the original idea, but I could not figure a reasonable way to make it memory safe without the compiler knowing about it. The easiest way to have the compiler know about it is to make it some sort of class type, not a struct type.

October 10, 2013
On 6/27/2013 11:33 AM, Rainer Schuetze wrote:
> On 27.06.2013 19:04, Walter Bright wrote:
>>> IIRC you also have the GC handbook book on your shelf. Check the
>>> chapters on RC, especially algorithm 18.2 "Eager reference counting with
>>> CompareAndSwap is broken".
>>
>> I have the book, but it is the first edition and there's no chapter 18
>> in it :-(
>
> I can remove the dust from my scanner to copy the 3 mostly relevant pages and send them to you.
>
>

I understand the issue (I think), but I can't think of a case where the ref count would be 1 when this happens.

October 10, 2013
On 6/28/2013 1:55 AM, Rainer Schuetze wrote:
>
> What happens if the class also implements interfaces? A reference of the interface type must do reference counting as well. So the interface must also define AddRef and Release. This is currently true for COM-interfaces derived from IUnknown, but not for other interfaces.
>
>

Even implementing IUnknown is a problem, if we do the suggestion that opAddref and opRelease be used as wrappers around AddRef and Release.

I think the simplest thing is to not allow ref counted classes to implement interfaces other than ones derived from IUnknown.

October 10, 2013
Rainer Schuetze wrote:

On 29.06.2013 00:22, Walter Bright wrote:
>> Any parameter of type C is also lowered to shared_ptr!C.
>
> I don't see how lowering C to shared_ptr!C and lowering share_ptr!C to C
> can work?

I don't see why you would want to lower from shared_ptr!C to C. It's only inside shared_ptr where access to the non-lowered C is needed, e.g. by disabling the lowering inside the shared_ptr. I was referring to "raw" references before, so the lowering would be better shared_ptr!(__raw(C)). But I agree, having the lowering include the original seems bad.

I realized a worse flaw with my proposal: it doesn't solve the assignment problem it was meant to. shared_ptr implemented as a struct does not have full control of the assignment, but is only called for the postblit and the destruction of the previous value. It has no way to put a lock around the full assignment. Still thinking too much C++...

Sorry for the noise.
October 10, 2013
On Thursday, 10 October 2013 at 02:19:02 UTC, Walter Bright wrote:
> >
> > @system code could, but it'd be extremely uneasy doing such
> calls unless I am the one in charge of that code and can make sure the base function will never store the (unretained) pointer somewhere it shouldn't now and in the future. An misstep here and you get memory corruption. Seriously, I don't think @system code should allow implicit conversions to the base class, it should be explicit.
>
> It's a worthy point.
>

It means OOP is completely broken with that design.
October 10, 2013
On 6/29/2013 12:16 AM, Rainer Schuetze wrote:
>
>
> Sorry for the noise.
>
>

No problem. It's a complicated subject, and none of us can think of all the ramifications. That's why this thread exists.

October 10, 2013
Rainer Schuetze wrote:

On 29.06.2013 06:38, Walter Bright wrote:
>
> On 6/27/2013 11:33 AM, Rainer Schuetze wrote:
>> On 27.06.2013 19:04, Walter Bright wrote:
>>>> IIRC you also have the GC handbook book on your shelf. Check the
>>>> chapters on RC, especially algorithm 18.2 "Eager reference counting
>>>> with
>>>> CompareAndSwap is broken".
>>>
>>> I have the book, but it is the first edition and there's no chapter 18
>>> in it :-(
>>
>> I can remove the dust from my scanner to copy the 3 mostly relevant
>> pages and send them to you.
>>
>>

I tried to scan it yesterday, but got large black bar at the fold (don't know if this the correct term) that eraased the first inch of text. I would have to rip the book apart to get better results.

>
> I understand the issue (I think), but I can't think of a case where the
> ref count would be 1 when this happens.
>
>


Consider a global shared reference R that holds the last reference to an object O. One thread exchanges the reference with another reference P while another thread reads the reference into S.

shared(C) R = O;      ; refcnt of O is 1

in pseudo-assembly missing null-checks:

Thread1 (R = P)        Thread2 (S = R)

                       mov ecx,[R]
                       ; thread suspended
mov eax,[P]
inc [eax].refcnt
mov ebx,[R]
mov [R],eax
dec [ebx].refcnt      ; refcnt of O now 0
jnz done
call delete_ebx
                       ; thread resumed
                       inc [ecx].refcnt
done:

The increment on [ecx].refcnt modifies garbage.
October 10, 2013
Rainer Schuetze wrote:
On 29.06.2013 09:36, Rainer Schuetze wrote:
>                         inc [ecx].refcnt
> done:
                          mov [S], ecx


Just wanted to add the book states that lock-free reference counting can be implemented with a cas2 operation modifying two seperate locations atomically. Unfortunately this operation does not exist in most processors. This might be the quoted paper: http://scholr.ly/paper/2199608/lock-free-reference-counting

October 10, 2013
On 6/29/2013 12:36 AM, Rainer Schuetze wrote:
> On 29.06.2013 06:38, Walter Bright wrote:
>>
>> On 6/27/2013 11:33 AM, Rainer Schuetze wrote:
>>> On 27.06.2013 19:04, Walter Bright wrote:
>>>>> IIRC you also have the GC handbook book on your shelf. Check the
>>>>> chapters on RC, especially algorithm 18.2 "Eager reference counting
>>>>> with
>>>>> CompareAndSwap is broken".
>>>>
>>>> I have the book, but it is the first edition and there's no chapter 18
>>>> in it :-(
>>>
>>> I can remove the dust from my scanner to copy the 3 mostly relevant
>>> pages and send them to you.
>>>
>>>
>
> I tried to scan it yesterday, but got large black bar at the fold (don't know if this the correct term) that eraased the first inch of text. I would have to rip the book apart to get better results.

Ah, don't rip up your book! (I cut the back off of mine and scanned it, but I no longer care to store the thousands of pounds of books I have anymore, and I like that my whole library fits on my laptop now!).

>
>>
>> I understand the issue (I think), but I can't think of a case where the
>> ref count would be 1 when this happens.
>>
>>
>
>
> Consider a global shared reference R that holds the last reference to an object O. One thread exchanges the reference with another reference P while another thread reads the reference into S.
>
> shared(C) R = O;      ; refcnt of O is 1
>
> in pseudo-assembly missing null-checks:
>
> Thread1 (R = P)        Thread2 (S = R)
>
>                        mov ecx,[R]
>                        ; thread suspended
> mov eax,[P]
> inc [eax].refcnt
> mov ebx,[R]
> mov [R],eax
> dec [ebx].refcnt      ; refcnt of O now 0
> jnz done
> call delete_ebx
>                        ; thread resumed
>                        inc [ecx].refcnt
> done:
>
> The increment on [ecx].refcnt modifies garbage.
>
>

Ok, I see. Let me think about it some more.
October 10, 2013
Jacob Carlborg:

On 29 jun 2013, at 06:42, Walter Bright wrote:

> I think the simplest thing is to not allow ref counted classes to implement interfaces other than ones derived from IUnknown.

What about Objective-C interfaces?