On Mon, Aug 15, 2005 at 12:40:05 +0100, Adrian Howard wrote:
> On 15 Aug 2005, at 02:13, David Formosa ((aka ? the Platypus)) wrote:
> 
> >After a very fruitful discussion I've rewritten my suggested GC API.
> >Comments please.
> [snip]
> 
> I'm speaking from complete ignorance since I've only been vaguely  following 
> the subject... but four additional things that strike me as  useful (because 
> I found them so in 
> Pop-11 when I used it) would be:
> 
> 1) Some way of declaring objects as being "fixed" so we can pass them  to 
> external code without having to worry about the GC moving them  around.

A handle to an object should always be fixed, I would think... Even
under a copying mechanism, you can have an arena for handles, and an
arena for the actual data which is actually collected, and points
back to the data.

Optimized access (auto unboxing, various inferrencing by the
compiler) could be made such that it doesn't go through the handle
unless absolutely necessary.

> 2) Some way of being able to tell the garbage collector to ignore the  
> current contents of the heap for the purposes of GC. One Pop-11 idiom  was to 
> do something like:
> 
>      ;;; create a whole bunch of complicated self referencing
>      ;;; objects that we know are going to persist over time
> 
>      sys_garbage();    ;;; run the garbage collector
>      sys_lock_heap();  ;;; lock stuff currently in the heap
> 
>      ;;; do lots of stuff that now runs quicker since the GC doesn't
>      ;;; have to worry about marking the objects that we know are
>      ;;; not going away
> 
>      sys_unlock_heap();    ;;; give the GC full rein again

We are trying to design a requirement based interface, so that the
GC can be changed, but behavior remains consistent.

This should be more like 

                do :GC::priority(:low) {
                        # anything that isn't GC::timely or possibly affecting
                        # something that is GC::timely is not cleaned up till
                        # later
                }

                do :GC::nodelay {
                        # the GC can work, but timeliness and throughput are
                        # ignored for the sake of performance of "real" code
                        # this means that most GCs are disabled, but a
                        # background thread GC will just have it's priority
                        # lowered

                        # implies that 'timely' now means 'at some point'
                }

                do :GC::nodestroy {
                        # the GC is told to completely freeze the state of
                        # things, delaying all work until after the block exits
                        # this means that you can rely on GC::timely objects
                        # being alive even when they shouldn't be.

                        # this is orthogonal to GC::nodelay - under plain
                        # GC::disabled objects may be collected for overall
                        # performance reasons, and then simply put on the
                        # finalize queue for finalization on block exit.

                        # applying both nodelay and nodestroy causes the GC
                        # system to completely turn off, so that objects are
                        # neither finalized nor collected.
                }

                do :GC::disabled {
                        # nodelay and nodestroy together
                }

                do :GC::priority(:high) {
                        # work very hard to conserve memory
                }

                do :GC::critical {
                        # it's like GC::timely for everything
                }

Possibly with e.g. $*RUNTIME.Memory.GarbageCollector.disable thrown
in for flexibility.

Block scoped behavior has some advantages:

        Exceptions raised from the block will cause augmented behavior
        to be reverted on scope exit

        Structure is clearer

But it's not as capable, since behavior cannot be changed to affect
calling scopes. This is important, but should be discouraged from
normal use.

> 3) Some way of marking structures/fields so their reference doesn't  count. 
> Weakrefs basically.

Yes... i think this is a container trait. Anybody got an opinion?

        my $var is weakref = $object;

> 4) Hooks to run code before/after GC. Occasionally very useful. (e.g.  with 
> the gc hooks and heap locking/unlocking you could implement your  own 
> ephemeral GC system in Pop-11).

This is possibly done by introspecting
$*RUNTIME.Memory.GarbageCollector, and seeing if it supports events.

What if it's a thread continuously running in the background, which
is only synched when something GC::timely may be involved?

This is getting me thinking though:

        $*RUNTIME.Memory.GarbageCollector.dispose($object); # force it,
        # even if it should be alive

        $*RUNTIME.Memory.GarbageCollector.clean($object); # check it

These two are non recursive by default, and they accept the
':recursive(1)' optional param to imply that referred subobjects
should be applied too. They should also allow very tight loops to be
controlled under do :GC::disabled, without wasting lots of memory.

On block exit a consistent state is reached - any timely objects
that should have been destroyed in the nested block will be
finalized.

Hmmm... ;-)

        sub nothingness () {
                $*RUNTIME.Memory.GarbageCollector.dispose($*RUNTIME, 
:recursive(1));
        }

-- 
 ()  Yuval Kogman <[EMAIL PROTECTED]> 0xEBD27418  perl hacker &
 /\  kung foo master: /me sneaks up from another MIME part: neeyah!!!!!

Reply via email to