@nogc, exceptions, generic containers... Issues.
Meta via Digitalmars-d
digitalmars-d at puremagic.com
Mon Sep 8 22:13:41 PDT 2014
On Monday, 8 September 2014 at 15:55:53 UTC, monarch_dodra wrote:
> 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.
It's not really a solution, but use of Nullable (or a theoretical
option type) and a Result type in @nogc code can help remove the
need for exceptions. An interesting data point is that Rust has a
try! macro, which wraps an expression and translates into
something like the following:
let ratio = try!(div(x, y));
becomes
let ratio = match div(x, y)
{
Ok(val) => val,
Err(msg) => { return Err; }
}
Maybe we need a similar solution for @nogc.
More information about the Digitalmars-d
mailing list