Thread overview
@safe RCSlice with DIP1000 + runtime checks
Sep 02, 2016
Nick Treleaven
Sep 02, 2016
rikki cattermole
Sep 03, 2016
Nick Treleaven
Sep 03, 2016
rikki cattermole
Sep 03, 2016
Nick Treleaven
September 02, 2016
Hi,
I've been working on a proof of concept Reference Counted Slice container, based on the one in DIP1000. That one now has opAssign marked @system, see:

https://github.com/dlang/DIPs/blob/master/DIPs/DIP1000.md#owning-containers

So I decided to make an RCSlice with a @safe opAssign (and @safe destroy, std.algorithm.move). opIndex is no longer a direct member, instead indexing RCSlice causes the compiler to create a RCRef temporary struct (via alias this), which does have opIndex:

https://github.com/ntrel/stuff/blob/master/typecons/rcref.d

The temporary struct is a private type, returned as an rvalue, so can't itself be passed by ref, so it should avoid the paired ref argument case mentioned in the above DIP1000 link.

RCRef increments *RCSlice.count on construction and decrements on destruction, but first checks that *count is > 1. If this fails, an AssertError is thrown. When -noboundschecks is passed, the code assumes no safety checks should be made for RCSlice and compiles out all the additional counting code.

Of course it would be great to have compile-time checks, so I'm looking forward to a DIP for that. But in the meantime this appears to show D can have @safe ref-counting now that DIP1000 is underway.

Thoughts?
September 02, 2016
On 02/09/2016 11:18 PM, Nick Treleaven wrote:
> Hi,
> I've been working on a proof of concept Reference Counted Slice
> container, based on the one in DIP1000. That one now has opAssign marked
> @system, see:
>
> https://github.com/dlang/DIPs/blob/master/DIPs/DIP1000.md#owning-containers
>
> So I decided to make an RCSlice with a @safe opAssign (and @safe
> destroy, std.algorithm.move). opIndex is no longer a direct member,
> instead indexing RCSlice causes the compiler to create a RCRef temporary
> struct (via alias this), which does have opIndex:
>
> https://github.com/ntrel/stuff/blob/master/typecons/rcref.d
>
> The temporary struct is a private type, returned as an rvalue, so can't
> itself be passed by ref, so it should avoid the paired ref argument case
> mentioned in the above DIP1000 link.
>
> RCRef increments *RCSlice.count on construction and decrements on
> destruction, but first checks that *count is > 1. If this fails, an
> AssertError is thrown. When -noboundschecks is passed, the code assumes
> no safety checks should be made for RCSlice and compiles out all the
> additional counting code.
>
> Of course it would be great to have compile-time checks, so I'm looking
> forward to a DIP for that. But in the meantime this appears to show D
> can have @safe ref-counting now that DIP1000 is underway.
>
> Thoughts?

I've got a much more advanced memory management solution[0].
I'm waiting on DIP1000 implementation before implementing it into it.

But over all I quite like this type approach.

[0] https://github.com/rikkimax/alphaPhobos/blob/master/source/std/experimental/memory/managed.d#L255

September 03, 2016
On Friday, 2 September 2016 at 11:42:57 UTC, rikki cattermole wrote:
> I've got a much more advanced memory management solution[0].
> I'm waiting on DIP1000 implementation before implementing it into it.
>
> But over all I quite like this type approach.
>
> [0] https://github.com/rikkimax/alphaPhobos/blob/master/source/std/experimental/memory/managed.d#L255

OK. Looks quite complex. Do you have the docs generated anywhere?
September 03, 2016
On Friday, 2 September 2016 at 11:18:58 UTC, Nick Treleaven wrote:
> RCRef increments *RCSlice.count on construction and decrements on destruction, but first checks that *count is > 1. If this fails, an AssertError is thrown. When -noboundschecks is passed, the code assumes no safety checks should be made for RCSlice and compiles out all the additional counting code.

BTW a similar approach would be to hold a RCSlice in the RCRef temporary, which is less efficient but causes no runtime errors. My way the user has to make their own temporary RCSlice copies when necessary.

> Of course it would be great to have compile-time checks, so I'm looking forward to a DIP for that.

(Actually I meant automatic creation of temporary RC objects when the compiler detects that they're necessary).
September 03, 2016
On 03/09/2016 11:02 PM, Nick Treleaven wrote:
> On Friday, 2 September 2016 at 11:42:57 UTC, rikki cattermole wrote:
>> I've got a much more advanced memory management solution[0].
>> I'm waiting on DIP1000 implementation before implementing it into it.
>>
>> But over all I quite like this type approach.
>>
>> [0]
>> https://github.com/rikkimax/alphaPhobos/blob/master/source/std/experimental/memory/managed.d#L255
>>
>
> OK. Looks quite complex. Do you have the docs generated anywhere?

Docs[0].

Before implementing as a library solution I was working on a language concept[1]. The basic idea is that the end user should never care about how memory is 'owned'. The main thing to know is that it isn't plain old data that you can do literally anything you want with it.

So these are valid transformations:
- managed!T -> scope T
- managed!(T[]) -> managed!(T[])
- managed!(T[]) -> T if(isBasicType!T)
- managed!(T[]) -> managed!T if(!isBasicType!T)

T cannot be a pointer but it can be an array, class, struct or primitive type. If you do pass a pointer it will *value so it acts as if it was typeof(*T.init) when accessing.

The current implementation is fairly dumb in that it does two allocations per memory instance. But that is an implementation detail.

So this is hugely over kill for most people but would be amazing what you could do for containers.

[0] http://cattermole.co.nz/docs/html/std_experimental_memory_managed.html
[1] https://wiki.dlang.org/User:Alphaglosined/ManagedMemory