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