February 24, 2015
On 2/23/2015 9:59 PM, Jonathan M Davis via Digitalmars-d wrote:
> And delete is supposed to have been deprecated ages ago, but yeah, it
> _definitely_ shouldn't be considered @safe.

Managing memory always is going to be unsafe. The idea is to encapsulate that, which RCArray shows how to do.

February 24, 2015
On Monday, February 23, 2015 23:02:03 Walter Bright via Digitalmars-d wrote:
> On 2/23/2015 9:59 PM, Jonathan M Davis via Digitalmars-d wrote:
> > And delete is supposed to have been deprecated ages ago, but yeah, it _definitely_ shouldn't be considered @safe.
>
> Managing memory always is going to be unsafe. The idea is to encapsulate that, which RCArray shows how to do.

That's fine. The issue is that delete is considered @safe by the compiler, not with the idea of RCArray. This code shouldn't compile:

void main() @safe
{
    auto i = new int(5);
    delete i;
}

and it does. Of course, delete is supposed to have been deprecated, but no one has gotten around to doing it. So, maybe that's why no one made it so that it was treated correctly with regards to @safe.

- Jonathan M Davis

February 24, 2015
On 2/24/2015 1:32 AM, Jonathan M Davis via Digitalmars-d wrote:
> The issue is that delete is considered @safe by the compiler,

I thought more people would be interested in how to do a memory safe reference counted container.

February 24, 2015
On Tuesday, 24 February 2015 at 09:44:13 UTC, Walter Bright wrote:
> On 2/24/2015 1:32 AM, Jonathan M Davis via Digitalmars-d wrote:
>> The issue is that delete is considered @safe by the compiler,
>
> I thought more people would be interested in how to do a memory safe reference counted container.

This is really interesting ! Thought as a beginner, I am wondering why the counter need to be a pointer ?
February 24, 2015
On Tuesday, 24 February 2015 at 10:08:23 UTC, matovitch wrote:
> On Tuesday, 24 February 2015 at 09:44:13 UTC, Walter Bright wrote:
>> On 2/24/2015 1:32 AM, Jonathan M Davis via Digitalmars-d wrote:
>>> The issue is that delete is considered @safe by the compiler,
>>
>> I thought more people would be interested in how to do a memory safe reference counted container.
>
> This is really interesting ! Thought as a beginner, I am wondering why the counter need to be a pointer ?

That's why:
----
this(this)
{
    if (count)
        ++*count;
}
----
February 24, 2015
On Tuesday, 24 February 2015 at 10:11:02 UTC, Namespace wrote:
> On Tuesday, 24 February 2015 at 10:08:23 UTC, matovitch wrote:
>> On Tuesday, 24 February 2015 at 09:44:13 UTC, Walter Bright wrote:
>>> On 2/24/2015 1:32 AM, Jonathan M Davis via Digitalmars-d wrote:
>>>> The issue is that delete is considered @safe by the compiler,
>>>
>>> I thought more people would be interested in how to do a memory safe reference counted container.
>>
>> This is really interesting ! Thought as a beginner, I am wondering why the counter need to be a pointer ?
>
> That's why:
> ----
> this(this)
> {
>     if (count)
>         ++*count;
> }
> ----

Hmm, I don't see why that's why... :(
February 24, 2015
On Tuesday, 24 February 2015 at 10:13:36 UTC, matovitch wrote:
> On Tuesday, 24 February 2015 at 10:11:02 UTC, Namespace wrote:
>> On Tuesday, 24 February 2015 at 10:08:23 UTC, matovitch wrote:
>>> On Tuesday, 24 February 2015 at 09:44:13 UTC, Walter Bright wrote:
>>>> On 2/24/2015 1:32 AM, Jonathan M Davis via Digitalmars-d wrote:
>>>>> The issue is that delete is considered @safe by the compiler,
>>>>
>>>> I thought more people would be interested in how to do a memory safe reference counted container.
>>>
>>> This is really interesting ! Thought as a beginner, I am wondering why the counter need to be a pointer ?
>>
>> That's why:
>> ----
>> this(this)
>> {
>>    if (count)
>>        ++*count;
>> }
>> ----
>
> Hmm, I don't see why that's why... :(

It's more effective if you figure it out on your own.
But maybe this is a bit more clear?
https://github.com/Dgame/m3/blob/master/SmartPointer.d#L106
February 24, 2015
On Tuesday, 24 February 2015 at 10:13:36 UTC, matovitch wrote:
> On Tuesday, 24 February 2015 at 10:11:02 UTC, Namespace wrote:
>> On Tuesday, 24 February 2015 at 10:08:23 UTC, matovitch wrote:
>> That's why:
>> ----
>> this(this)
>> {
>>    if (count)
>>        ++*count;
>> }
>> ----
>
> Hmm, I don't see why that's why... :(

The counter is shared amount all "copies" of the array.
February 24, 2015
On Tuesday, 24 February 2015 at 10:16:00 UTC, Ulrich Küttler wrote:
> On Tuesday, 24 February 2015 at 10:13:36 UTC, matovitch wrote:
>> On Tuesday, 24 February 2015 at 10:11:02 UTC, Namespace wrote:
>>> On Tuesday, 24 February 2015 at 10:08:23 UTC, matovitch wrote:
>>> That's why:
>>> ----
>>> this(this)
>>> {
>>>   if (count)
>>>       ++*count;
>>> }
>>> ----
>>
>> Hmm, I don't see why that's why... :(
>
> The counter is shared amount all "copies" of the array.

Ah yes, what an idiot ! Thanks !

February 24, 2015
On Monday, 23 February 2015 at 22:15:54 UTC, Walter Bright wrote:
> This is pretty straightforward. More could be done:
>
> 1. small array optimization
> 2. support for ranges as constructor args
> 3. present a range interface
> 4. support for malloc/free instead of GC
> 5. bounds checking
> 6. the array[] and the count could be allocated together
> 7. array[] could be just a pointer
>
> but the basic idea is there, I didn't want to hide it behind all the other flesh a professional type would have.
>
> Note the return in opIndex(). This is DIP25 at work!
>
> Compile:
>     dmd rcarray -unittest -main -dip25
>
> ===========================================
>
> struct RCArray(E) {
>
>     this(E[] a)
>     {
>         array = a.dup;
>         start = 0;
>         end = a.length;
>         count = new int;
>         *count = 1;
>     }
>
>     ~this()
>     {
>         if (count && --*count == 0)
>             delete array;
>     }
>
>     this(this)
>     {
>         if (count)
>             ++*count;
>     }
>
>     size_t length()
>     {
>         return end - start;
>     }
>
>     ref E opIndex(size_t i) return // here's the magic
>     {
>         return array[start + i];
>     }
>
>     RCArray opSlice(size_t lwr, size_t upr)
>     {
>         RCArray result = this;
>         result.start = start + lwr;
>         result.end = start + upr;
>         return result;
>     }
>
>   private:
>     E[] array;
>     size_t start, end;
>     int* count;
> }
>
> unittest
> {
>     static int[3] s = [7, 6, 4];
>     auto r = RCArray!int(s);
>     assert(r.length == 3);
>     assert(r[0] == 7);
>     assert(r[1] == 6);
>     assert(r[2] == 4);
>     assert(*r.count == 1);
>
>     {
>         auto r2 = r;
>         assert(r2[0] == 7);
>         assert(r2[1] == 6);
>         assert(r2[2] == 4);
>         assert(*r.count == 2);
>
>         r[1] = 3;
>         assert(r2[0] == 7);
>         assert(r2[1] == 3);
>         assert(r2[2] == 4);
>     }
>     assert(*r.count == 1);
>
>     auto r3 = r[1 .. 3];
>     r[2] = 9;
>     assert(r3[0] == 3);
>     assert(r3[1] == 9);
>
>   /+
>     ref int test(ref RCArray!int rr)
>     {
>         return rr[1]; // this gives error
>     }
>    +/
> }

Thanks for the example.

I think we need more practical stuff like this compiled somewhere on the homepage, especially when a new feature is introduced, to answer questions like: What is it? When should I use it? And how do I implement it? Saves a lot of time and the frustration of finding out later that there _is_ such a feature, only I never heard of it until now.