www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - safe RCSlice with DIP1000 + runtime checks

reply Nick Treleaven <nick geany.org> writes:
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?
Sep 02 2016
next sibling parent reply rikki cattermole <rikki cattermole.co.nz> writes:
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
Sep 02 2016
parent reply Nick Treleaven <nick geany.org> writes:
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?
Sep 03 2016
parent rikki cattermole <rikki cattermole.co.nz> writes:
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
Sep 03 2016
prev sibling parent Nick Treleaven <nick geany.org> writes:
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).
Sep 03 2016