@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