I've added post-gc-hooks parameter to revision 1833.  Basically, it's
a list of thunks that are invoked after garbage collection.  If the
hooks themselves cause GC, then they are run again, iteratively, until
they run without triggering GC (and thus have nothing more to do).
While running the hooks, the post-gc-hooks is parameterized to be '()
so as to avoid recursive calls to the hooks.  So, the loop terminates
as long as one run of all the hooks does not GC.  E.g.,
(parameterize ([post-gc-hooks (list (collect))])
  (collect))
would run forever.

On Jul 29, 2009, at 4:05 AM, Vincent Manis wrote:

The two practical applications for this that I can imagine are running
finalizers and doing user-defined logging collections. So if the handler
is limited in what it can do, that's fine with me.

The problem is that it's very hard to limit what it can do.  The only
thing it cannot do in the current design is to change the post-gc-hooks
since these are reinstated to their value prior to calling the hooks.

I prefer the strategy where the handler runs after the collector is finished,
making for an `after-gc-is-complete' hook.

Yes.  This is what I opted to, instead of Chez's gc-"request"-hooks.

If the handler wants to call the GC, that should work OK, and wouldn't be a
true recursive GC call;

The handler can cause GC, but it should not, in general, explicitly call
(collect).

I feel totally neutral about the handler invoking itself recursively,
and probably would at least want to discourage it, even if it were easy to
implement.

I think it would be nasty (for the user) if it did.  Handlers installed
while inside the handler should be called though if GC happens during
the extent of these handlers.

A policy that prohibited calling the GC, calling the handler
recursively, or mutating GC handling in other ways (replacing the handler,
for example), from inside the handler would be fine with me.

I think the design above meets your needs then.

Such a handler can still exhibit all the nasty characteristics of any
asynchronously-called callback, but some proper structuring of the handler
should render the asynchrony manageable. I do NOT want to ask you to
implement things that would be `fun to debug', at least not unless you
want to! :-).

What I meant was "fun for the user to debug", but I think doing non- recursive
handling of post-gc-hooks makes it a better design and takes some of the
fun away.  :-)

In my graduate days, I worked as a peon on a never-completed ALGOL 68 compiler.
Every design decision was premised on the theory that there could be
`fifty pages of code between this pair of parentheses', even though the average use case had half a dozen tokens. This left me with a cordial distaste for design philosophies based on allowing everything that is humanly conceivable,
useful or not.

Luckily, this one did not need 50 pages of code.  It was like 20 lines.

I guess it's pretty obvious that I'd like to be able to finalize and
reap inaccessible values registered with a guardian automatically on GC.

What kind of resource are you protecting? Is the usual strategy (e.g., finalizing dead resources when new resources are created) not sufficient
in your case?  This is what Ikarus uses for file handlers.
In this particular example, I have resources (server connections, actually) that are all created early in execution, and then it's likely that no more will be created. So the GC represents an opportunity to catch these defunct
values and close them properly.

Just remember that there are no guarantees on when the GC discovers that
objects are dead.  Consequently, these handlers should remain installed
until they're guaranteed to be no longer needed.  I don't know the best
way to make a handler uninstall itself cleanly.  Maybe it's not too
important, since I don't think you'd have more than a few such hooks at
any given time.  But if you have any ideas, do let me know.

Aziz,,,

Reply via email to