digitalmars.D - safe RCSlice with DIP1000 + runtime checks
- Nick Treleaven (23/23) Sep 02 2016 Hi,
- rikki cattermole (6/28) Sep 02 2016 I've got a much more advanced memory management solution[0].
- Nick Treleaven (3/9) Sep 03 2016 OK. Looks quite complex. Do you have the docs generated anywhere?
- rikki cattermole (20/30) Sep 03 2016 Docs[0].
- Nick Treleaven (7/14) Sep 03 2016 BTW a similar approach would be to hold a RCSlice in the RCRef
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
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
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#L255OK. Looks quite complex. Do you have the docs generated anywhere?
Sep 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: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/ManagedMemoryI'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#L255OK. Looks quite complex. Do you have the docs generated anywhere?
Sep 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).
Sep 03 2016