digitalmars.D - RefCounted implementation questions
- Johannes Pfau (68/68) Jul 25 2011 Reposting from D.learn (Warning: long post ahead):
- Andrej Mitrovic (2/2) Jul 26 2011 More bugs:
Reposting from D.learn (Warning: long post ahead): Possible bugs: The removeRange and addRange calls are not always paired? if (sz >= size_t.sizeof && p.ptr) GC.addRange(p.ptr, sz); if (hasIndirections!T && RefCounted._store) GC.removeRange(RefCounted._store); Now say, I store a single byte, wouldn't addRange get called but removeRange not? Same should be true for any type without indirection. As Andrej Mitrovic pointed out in D.learn, RefCounted creates a spurious destructor call: See his example: https://gist.github.com/1103852 the output is dealloc alloc dealloc I assume this wasn't an issue for std.container.Array and phobos in general, as those only use RefCounted for memory management. free doesn't care if it's called with a null pointer, but if ref-counting is used with some kind of handle, this can be problematic. If this spurious destructor call can't be avoided, it should be documented at least, so that it can be worked around in the user code with a additional null-pointer check. Possible performance issues: (Background: I read that "addRange and removeRange are terribly inefficient" if that's wrong, there's no issue) RefCounted calls addRange if the _store size is >= size_t. (see https://github.com/D-Programming-Language/phobos/blob/master/std/typecons.d#L2304 ) * As _store already has a size_t field for count, addRange will always be called? * This means even if I only want ref-counting for a simple C handle, addRange will be called. Shouldn't it be possible to explicitly disable addRange? Maybe an additional NeedsScanning template parameter for the RefCounted struct would be useful? Original question from D.learn: I don't understand the use of malloc & free in RefCounted. If addRange is called anyway, why not just use GC.malloc and GC.free? I now see that this wouldn't work as the GC's nondeterminism could cause problems with RefCounted structs in heap memory. Maybe we should have an additional allocator returning memory which is scanned by the GC, but not automatically collected. This way we should be able to save some addRange calls. Feature requests: If a ref-counted struct is used inside a class, we currently lose all advantages of reference-counting. Such classes often have dispose or similar methods used to explicitly free resources. Those cannot interact with RefCounted though, as RefCounted doesn't have a function to decrease the reference count explicitly. Would a detach method like this work? https://gist.github.com/1103866 It's only the RefCounted destructor with an additional "RefCounted._store = null;" in line 11 to prevent the destructor or another detach call to decrease the reference count again. Including an example like this one from Jesse Phillips in the doc would also be quite useful: there's a small mistake in the last line of the example, this(HANDLE h) { _data = h; } should be this(HANDLE h) { _data = Data(h); } or this(HANDLE h) { _data.RefCounted.initialize(h); } -- Johannes Pfau
Jul 25 2011
More bugs: http://codepad.org/LhztsOC9
Jul 26 2011