RFC: reference counted Throwable
Adam D. Ruppe via Digitalmars-d
digitalmars-d at puremagic.com
Sat Sep 20 07:31:34 PDT 2014
How often do you store an exception reference anyway that escapes
a catch block? I think all this talk is overkill to solve a
non-problem in 99% of practice.
Correct me if I'm wrong, but aren't *all* exceptions in a
particular thread generally unreferenced at the end of a catch()
block, unless the programmer explicitly escaped that reference?
If so, we don't need refcounting! Here's my solution:
1) Throwables are allocated in a separate thread-local memory
pool than most other objects. The @nogc version just aborts the
program if this pool ever runs out of memory. The gc version can
do a collection cycle and grow the size if necessary. (Though if
you need a lot of Throwable objects alive at once, I question wtf
is up with your code...)
2) class Throwable adds a method, gcClone, which copies it to the
regular GC heap for those cases when you do want to store it or
pass it between threads or whatever.
3) A function, @system void clearExceptions() is added. You may
manually call this when you are done handling exceptions in this
thread.
4) Might also have @safe void prepareExceptions() which
pre-allocates the pool. This could also be done automatically or
on demand or whatever.
Advantages:
* Throwables are still GC managed as far as most code is
concerned. The only time you need caution is if you call the new
@system function to free the pool... and even then, you just make
sure you don't escape those references before you do.
* If you want to avoid the GC, just manually clear your
exceptions from time to time.
* Allocating/deallocating from this specialized memory pool is
prolly faster than any other scheme anyway.
* No language changes required, this is all library stuff.
Disadvantages:
* There's a few manual steps to get all the benefit. (We could
insert a call to clearExceptions at the end of catch blocks
automatically, but without a static check to ensure the objects
actually haven't escaped, this would break memory safety. But a
manual call isn't that big of a deal)
* If you do it wrong, you'll be annoyed.
* ???
I really think this is a win. I've done a proof of concept before
by hacking _d_newclass to use the pool based on the TypeInfo
passed in, gives a speedup in all the simple cases I tried. But
since that hack still uses new, it wouldn't pass the @nogc test.
However, a library function like emplace could be @nogc and do
the same thing. Since @nogc is an addition to the function,
you'll be modifying it anyway, so changing "throw new" to
whatever the new lib function is called can be done at the same
time.
It is the catch code that have to worry about freeing the
pool.... and even then, only if you want to avoid the GC. Normal
code can just let the pool be collected when it is collected.
I think I'll write a little module we can play with.
More information about the Digitalmars-d
mailing list