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.

Reply via email to