On Tue, Dec 19, 2023 at 11:21 PM Marc Feeley <xxxxxx@iro.umontreal.ca> wrote:

Imagine a concurrent program with N threads calling guardian-try-collect on various guardians for which no object gets enqueued. This will cause N GCs in rapid succession, with no computational progress happening. In the case where at least one object gets enqueued there is a possible improvement in performance by stopping the GC as soon as the first object gets enqueued, but this requires non-trivial changes to the garbage collector (how would you modify a parallel garbage collector) and there is no guarantee that the object gets enqueued early in the GC cycle.

That is indeed a problem.  It's possible to optimize it a bit by having -try-collect check if the GC is running and not start another GC in that case, although it is still possible not to wind up not collecting anything because the objects in the second guardian have already been processed by the GC.

However, guardian-wait has a comparable problem: it is necessary to have one thread per guardian in order not to get hung by waiting on the wrong guardian.  In a Scheme where threads are heavyweight (e.g. Posix) this will not scale.  The issue could be circumvented by providing meta-guardians which make available not garbage objects but ready-to-go guardians or meta-guardians.  Unfortunately, this stacks up layers of abstractions.

A simpler strategy is to optionally associate a closure with each guardian which is invoked when the guardian is ready; then there is no need for either -wait or -try-collect, as all the closures can run on a single thread.

Overall though I think it is better if we leave out async support altogether and provide it in a later SRFI, if at all.  It is still possible to handle cases like the Abstract Example by reclaiming at least one instance of a resource just before allocating a new one.