www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - RefCounted implementation questions

reply Johannes Pfau <spam example.com> writes:
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:
http://stackoverflow.com/questions/4632355/making-a-reference-counted-object-in-d-using-refcountedt/4635050#4635050

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
parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
More bugs:

http://codepad.org/LhztsOC9
Jul 26 2011