diff options
-rw-r--r-- | gc.c | 20 | ||||
-rw-r--r-- | gc.h | 2 | ||||
-rw-r--r-- | share/txr/stdlib/struct.tl | 3 | ||||
-rw-r--r-- | struct.c | 2 | ||||
-rw-r--r-- | txr.1 | 44 |
5 files changed, 45 insertions, 26 deletions
@@ -808,18 +808,28 @@ static val gc_wrap(void) return nil; } -val gc_finalize(val obj, val fun) +val gc_finalize(val obj, val fun, val rev_order_p) { type_check(fun, FUN); + rev_order_p = default_bool_arg(rev_order_p); + if (is_ptr(obj)) { struct fin_reg *f = coerce(struct fin_reg *, chk_malloc(sizeof *f)); f->obj = obj; f->fun = fun; f->reachable = 0; - f->next = 0; - *final_tail = f; - final_tail = &f->next; + + if (rev_order_p) { + if (!final_list) + final_tail = &f->next; + f->next = final_list; + final_list = f; + } else { + f->next = 0; + *final_tail = f; + final_tail = &f->next; + } } return obj; } @@ -828,7 +838,7 @@ void gc_late_init(void) { reg_fun(intern(lit("gc"), system_package), func_n0(gc_wrap)); reg_fun(intern(lit("gc-set-delta"), system_package), func_n1(gc_set_delta)); - reg_fun(intern(lit("finalize"), user_package), func_n2(gc_finalize)); + reg_fun(intern(lit("finalize"), user_package), func_n3o(gc_finalize, 2)); } /* @@ -35,7 +35,7 @@ int gc_state(int); void gc_mark(val); void gc_conservative_mark(val); int gc_is_reachable(val); -val gc_finalize(val obj, val fun); +val gc_finalize(val obj, val fun, val rev_order_p); #if CONFIG_GEN_GC val gc_set(loc, val); diff --git a/share/txr/stdlib/struct.tl b/share/txr/stdlib/struct.tl index c8eadc8b..24bccbe5 100644 --- a/share/txr/stdlib/struct.tl +++ b/share/txr/stdlib/struct.tl @@ -117,7 +117,8 @@ ,*(cdr instance-init-form)))) ,*(if (cdr instance-fini-form) ^((finalize ,arg-sym (lambda (,(car instance-fini-form)) - ,*(cdr instance-fini-form))))))) + ,*(cdr instance-fini-form)) + t))))) ,(if args (let ((gens (mapcar (ret (gensym)) args))) ^(lambda (,arg-sym ,*gens) @@ -205,7 +205,7 @@ val make_struct_type(val name, val super, st->initfun = initfun; st->boactor = boactor; - gc_finalize(stype, struct_type_finalize_f); + gc_finalize(stype, struct_type_finalize_f, nil); for (sl = 0, stsl = STATIC_SLOT_BASE, iter = all_slots; iter; @@ -17887,12 +17887,16 @@ the code, if any, has been executed. The registration takes place as if by the evaluation of the form .cblk -.meti (finalize << obj (lambda <> (param) << body-form ...)) +.meti (finalize << obj (lambda <> (param) << body-form ...) t) .cble where .meta obj -denotes the structure instance. - +denotes the structure instance. Note the +.code t +argument which requests reverse order of registration, ensuring that if an +object has multiple finalizers registered at different levels of inheritance +hierarchy, the finalizers specified for a derived structure type are called +before inherited finalizers. .RE .PP @@ -33608,7 +33612,7 @@ special builds of \*(TX for small systems. .coNP Function @ finalize .synb -.mets (finalize < object << function ) +.mets (finalize < object < function <> [ reverse-order-p ]) .syne .desc The @@ -33626,21 +33630,26 @@ will be called with .meta object as its only argument. -Finalizers are called in the same order in which they are registered: -newer registrations are called after older registrations. +Multiple finalizer functions can be registered for the same object. +They are all called when the object becomes unreachable. + +If the +.meta reverse-order-p +argument isn't specified, or is +.codn nil , +then finalizer is registered at the end of the list. If -.meta object -is registered multiple times by multiple calls to -.codn finalize , -then if those finalizers are called, they are all called, in the order -of registration. +.meta reverse-order-p +is true, then the finalizer is registered at the front of +the list. -After a finalization call takes place, its registration is removed; -.meta object -and -.meta function -are no longer associated. However, neither +Finalizers which are activated in the same finalization processing phase +are called in the order in which they appear in the +registration list. + +After a finalization call takes place, its registration is removed. However, +neither .meta object nor .meta function @@ -33652,8 +33661,7 @@ to store somewhere a persistent reference to .meta object or to itself, thereby reinstating these objects as reachable. -.meta function -is itself permitted to call +A finalizer is itself permitted to call .code finalize to register the original .code object |