@nogc, exceptions, generic containers... Issues.
monarch_dodra via Digitalmars-d
digitalmars-d at puremagic.com
Mon Sep 8 08:55:51 PDT 2014
I'm starting this thread related to two issues I'm encountering
in regards to avoiding the GC, and the new @nogc attribute.
1) Issue 1)
The first issue is in regards to Throwables. The issue here is
that they are allocated using the GC, so it is currently almost
impossible to throw an exception in a @nogc context. This is (I
think) a serious limitations. Do we have any plans, ideas, on how
to solve this?
A particularly relevant example of this issue is `RefCounted`:
This struct uses malloc to ref count an object, give a
deterministic life cycle, and avoid the GC. Yet, since malloc can
fail, it does this:
_store = cast(Impl*) enforce(malloc(Impl.sizeof));
Can you see the issue? This object which specifically avoids
using the GC, end up NOT being @nogc.
Any idea how to approach this problem?
I know there are "workarounds", such as static pre-allocation,
but that also comes with its own set of problems.
Maybe we could change it to say it's not legal to "hold on" to
exceptions for longer than they are being thrown? Then, we could
create the exceptions via allocators, which could
deterministically delete them at specific points in time (or by
the GC, if it is still running)? Just a crazy idea...
2) Issue 2)
The second issue is that data which is placed in non-GC *may*
still need to be scanned, if it holds pointers. You can check for
this with hasIndirections!T. This is what RefCounted and Array
currently do. This is usually smart. There's a catch though.
If the object you are storing happens to hold pointers, but NOT
to GC data, they are still scanned.
A tell-tale example of this problem is Array!int. You'd think
it's @nogc, right? The issue is that Array has a "Payload"
object, into which you place malloc'ed memory for your ints. The
Payload itself is placed in a RefCounted object. See where this
is going?
Even though we *know* the Payload is malloc'ed, and references
malloc'ed data, it is still added to the GC's ranges of scanned
data. Even *if* we solved issue 1, then Array!int would still
*not* be @nogc, even though it absolutely does not use the GC.
Just the same, an Array!(RefCounted!int) would also be scanned by
the GC, because RefCounted holds pointers...
A *possible solution* to this problem would be to add an extra
parameter to these templates called "ScanGC", which would be
initialized to "hasIndirection!T". EG:
struct Array(T, bool ScanGC = hasIndirections!T)
Does this seem like a good idea? I don't really see any other way
around this if we want generic code with manual memory
management, that is "GC friendly" yet still useable in a @nogc
context.
More information about the Digitalmars-d
mailing list