diff --git a/src/gasman.h b/src/gasman.h index 30300fe852..0f8cc2cc7e 100644 --- a/src/gasman.h +++ b/src/gasman.h @@ -348,7 +348,7 @@ static inline void SET_PTR_BAG(Bag bag, Bag *val) ** is incorrect as mentioned in the section for 'PTR_BAG' (see "PTR_BAG"). */ -#if !defined(USE_GASMAN) +#if defined(USE_BOEHM_GC) static inline void CHANGED_BAG(Bag bag) { @@ -370,7 +370,7 @@ static inline void CHANGED_BAG(Bag bag) extern void CHANGED_BAG(Bag b); -#else +#elif defined(USE_GASMAN) extern Bag * YoungBags; extern Bag ChangedBags; @@ -382,6 +382,10 @@ static inline void CHANGED_BAG(Bag bag) } } +#else + +#error unknown garbage collector + #endif diff --git a/src/weakptr.c b/src/weakptr.c index 979d6a8a70..6faf7742d7 100644 --- a/src/weakptr.c +++ b/src/weakptr.c @@ -10,10 +10,10 @@ *Y (C) 1998 School Math and Comp. Sci., University of St Andrews, Scotland *Y Copyright (C) 2002 The GAP Group ** -** This file contains the functions that deal with weak pointer objects +** This file contains the functions that deal with weak pointer objects. ** A weak pointer object looks like a plain list, except that its entries ** are NOT kept alive through a garbage collection (unless they are contained -** in some other kind of object). +** in some other kind of object). */ #include "weakptr.h" @@ -54,75 +54,94 @@ #elif defined(USE_BOEHM_GC) -#define IS_WEAK_DEAD_BAG(bag) (!(bag)) -#define REGISTER_WP(loc, obj) \ - GC_general_register_disappearing_link((void **)(loc), (obj)) -#define FORGET_WP(loc) \ - GC_unregister_disappearing_link((void **)(loc)) +static inline void REGISTER_WP(Obj wp, UInt pos, Obj obj) +{ + void ** ptr = (void **)(ADDR_OBJ(wp) + pos); + GC_general_register_disappearing_link(ptr, obj); +} + +static inline void FORGET_WP(Obj wp, UInt pos) +{ + void ** ptr = (void **)(ADDR_OBJ(wp) + pos); + GC_unregister_disappearing_link(ptr); +} #endif /**************************************************************************** ** -*F STORE_LEN_WPOBJ(,) . . . . . . . set the length of a WP object +*F STORE_LEN_WPOBJ(,) . . . . . . . . set the length of a WP object ** -** 'STORE_LEN_WPOBJ' sets the length of the WP object to . -** -** Note that 'STORE_LEN_WPOBJ' is a macro, so do not call it with arguments -** that have side effects. +** 'STORE_LEN_WPOBJ' sets the length of the WP object to . ** -** Objects at the end of wp may evaporate, so the stored length can only +** Objects at the end of may evaporate, so the stored length can only ** be regarded as an upper bound. */ - -#define STORE_LEN_WPOBJ(wp,len) (ADDR_OBJ(wp)[0] = (Obj)(len)) +static inline void STORE_LEN_WPOBJ(Obj wp, Int len) +{ + ADDR_OBJ(wp)[0] = (Obj)len; +} /**************************************************************************** ** -*F STORED_ LEN_WPOBJ(). . .. . . . . . . stored length of a WP Object +*F STORED_LEN_WPOBJ() . . . . . . . . . . . stored length of a WP object ** ** 'STORED_LEN_WPOBJ' returns the stored length of the WP object ** as a C integer. ** -** Note that 'STORED_LEN_WPOBJ' is a macro, so do not call it -** with arguments that have side effects. -** ** Note that as the list can mutate under your feet, the length may be -** an overestimate +** an overestimate. */ +static inline Int STORED_LEN_WPOBJ(Obj wp) +{ + return (Int)(CONST_ADDR_OBJ(wp)[0]); +} -#define STORED_LEN_WPOBJ(wp) ((Int)(CONST_ADDR_OBJ(wp)[0])) /**************************************************************************** ** -*F ELM_WPOBJ(,) . . . . . . . . . . . . . element of a WP object +*F ELM_WPOBJ(,) . . . . . . . . . . . . . get entry of a WP object ** -** 'ELM_WPOBJ' return the -th element of the WP object . must +** 'ELM_WPOBJ' return the -th element of the WP object . must ** be a positive integer less than or equal to the physical length of . ** If has no assigned element at position , 'ELM_WPOBJ' returns 0. -** -** If the entry died at a recent garbage collection, it will return a Bag ID -** for which IS_WEAK_DEAD_BAG will return 1 -** -** Note that 'ELM_WPOBJ' is a macro, so do not call it with arguments that -** have side effects. -** -** ELM_WPOBJ(,) is a valid lvalue and may be assigned to */ +static inline Obj ELM_WPOBJ(Obj list, UInt pos) +{ + Bag elm = CONST_ADDR_OBJ(list)[pos]; + +#ifdef USE_GASMAN + if (IS_WEAK_DEAD_BAG(elm)) { + ADDR_OBJ(list)[pos] = 0; + return 0; + } +#endif -#define ELM_WPOBJ(list,pos) (ADDR_OBJ(list)[pos]) + return elm; +} /**************************************************************************** ** -*F GROW_WPOBJ(,) . make sure a weak pointer object is large enough +*F SET_ELM_WPOBJ(,,) . . . . . . . . set entry of a WP object ** -** 'GROW_WPOBJ' grows the weak pointer object if necessary to -** ensure that it has room for at least elements. +** 'SET_ELM_WPOBJ' sets the -th element of the WP object to . */ +static inline void SET_ELM_WPOBJ(Obj list, UInt pos, Obj val) +{ + ADDR_OBJ(list)[pos] = val; +} + +/**************************************************************************** +** +*F GROW_WPOBJ(,) . . . ensure weak pointer object is large enough +** +** 'GROW_WPOBJ' grows the weak pointer object if necessary to ensure +** that it has room for at least elements. +*/ static inline void GROW_WPOBJ(Obj wp, UInt need) { UInt plen; /* new physical length */ @@ -150,11 +169,11 @@ static inline void GROW_WPOBJ(Obj wp, UInt need) volatile Obj tmp = ELM_WPOBJ(wp, i); MEMBAR_READ(); if (IS_BAG_REF(tmp) && ELM_WPOBJ(wp, i)) { - FORGET_WP(&ELM_WPOBJ(wp, i)); - REGISTER_WP(&ELM_WPOBJ(copy, i), tmp); + FORGET_WP(wp, i); + REGISTER_WP(copy, i, tmp); } - ELM_WPOBJ(wp, i) = 0; - ELM_WPOBJ(copy, i) = tmp; + SET_ELM_WPOBJ(wp, i, 0); + SET_ELM_WPOBJ(copy, i, tmp); } SET_PTR_BAG(wp, PTR_BAG(copy)); #else @@ -166,7 +185,7 @@ static inline void GROW_WPOBJ(Obj wp, UInt need) /**************************************************************************** ** -*F FuncWeakPointerObj( , ) . . . . . make a weak pointer object +*F FuncWeakPointerObj(,) . . . . . . make a weak pointer object ** ** Handler for the GAP function WeakPointerObject(), which makes a new ** WP object. @@ -194,11 +213,11 @@ Obj FuncWeakPointerObj(Obj self, Obj list) { #ifdef USE_BOEHM_GC Obj tmp = ELM0_LIST(list2, i); - ELM_WPOBJ(wp,i) = tmp; + SET_ELM_WPOBJ(wp, i, tmp); if (IS_BAG_REF(tmp)) - REGISTER_WP(&ELM_WPOBJ(wp, i), tmp); + REGISTER_WP(wp, i, tmp); #else - ELM_WPOBJ(wp,i) = ELM0_LIST(list,i); + SET_ELM_WPOBJ(wp, i, ELM0_LIST(list, i)); #endif CHANGED_BAG(wp); /* this must be here in case list is in fact an object and causes a GC in the @@ -211,11 +230,11 @@ Obj FuncWeakPointerObj(Obj self, Obj list) /**************************************************************************** ** -*F LengthWPObj() . . . . . . . . . . . . . . current length of WP Object +*F LengthWPObj() . . . . . . . . . . . . . . current length of WP object ** -** 'LengthWPObj()' returns the current length of WP Object as a C -** integer the value cannot be trusted past a garbage collection, as -** trailing items may evaporate. +** 'LengthWPObj' returns the length of the WP object as a C integer. +** The value cannot be trusted past a garbage collection, as trailing items +** may evaporate. ** ** Any identifiers of trailing objects that have evaporated in a garbage ** collection are cleaned up by this function. However, for HPC-GAP, this @@ -234,11 +253,9 @@ Int LengthWPObj(Obj wp) Obj elm; while (len > 0) { elm = ELM_WPOBJ(wp, len); - if (elm && !IS_WEAK_DEAD_BAG(elm)) + if (elm) break; changed = 1; - if (elm) - ELM_WPOBJ(wp, len) = 0; len--; } if (changed) @@ -248,12 +265,11 @@ Int LengthWPObj(Obj wp) /**************************************************************************** ** -*F FuncLengthWPObj() . . . . . . . . . . . . current length of WP Object +*F FuncLengthWPObj() . . . . . . . . . . . . current length of WP object ** -** 'FuncLengthWPObj()' is a handler for a GAP function that returns the -** current length of WP Object. The value cannot be trusted past a garbage +** 'FuncLengthWPObj' is a handler for a GAP function that returns the length +** of the WP object . The value cannot be trusted past a garbage ** collection, as trailing items may evaporate. -** */ Obj FuncLengthWPObj(Obj self, Obj wp) @@ -269,11 +285,10 @@ Obj FuncLengthWPObj(Obj self, Obj wp) /**************************************************************************** ** -*F FuncSetElmWPObj(, , , ) . set an entry in a WP Object +*F FuncSetElmWPObj(,,,) . . set an entry in a WP object ** -** 'FuncSetElmWPObj(, , , )' is a handler for a GAP -** function that sets an entry in a WP object. -** +** 'FuncSetElmWPObj' is a handler for a GAP function that sets an entry in +** a WP object. */ Obj FuncSetElmWPObj(Obj self, Obj wp, Obj pos, Obj val) @@ -312,12 +327,12 @@ Obj FuncSetElmWPObj(Obj self, Obj wp, Obj pos, Obj val) volatile Obj tmp = ELM_WPOBJ(wp, ipos); MEMBAR_READ(); if (IS_BAG_REF(tmp) && ELM_WPOBJ(wp, ipos)) - FORGET_WP(&ELM_WPOBJ(wp, ipos)); - ELM_WPOBJ(wp,ipos) = val2; + FORGET_WP(wp, ipos); + SET_ELM_WPOBJ(wp, ipos, val2); if (IS_BAG_REF(val2)) - REGISTER_WP(&ELM_WPOBJ(wp, ipos), val2); + REGISTER_WP(wp, ipos, val2); #else - ELM_WPOBJ(wp,ipos) = val; + SET_ELM_WPOBJ(wp, ipos, val); #endif CHANGED_BAG(wp); return 0; @@ -325,9 +340,9 @@ Obj FuncSetElmWPObj(Obj self, Obj wp, Obj pos, Obj val) /**************************************************************************** ** -*F IsBoundElmWPObj( , ) . . . . . is an entry bound in a WP Object +*F IsBoundElmWPObj(,) . . . . . is an entry bound in a WP object ** -** 'IsBoundElmWPObj( , )' returns 1 is there is (currently) a live +** 'IsBoundElmWPObj' returns 1 is there is (currently) a live ** value at position pos or the WP object wp and 0 otherwise, cleaning up a ** dead entry if there is one ** */ @@ -369,24 +384,17 @@ Int IsBoundElmWPObj( Obj wp, Obj pos) #else if (elm == 0) return 0; - if (IS_WEAK_DEAD_BAG(elm)) - { - ELM_WPOBJ(wp,ipos) = 0; - return 0; - } #endif return 1; } /**************************************************************************** ** -*F FuncIsBoundElmWPObj( , , ) . . . . . . .IsBound WP Object +*F FuncIsBoundElmWPObj(,,) . . IsBound handler for WP objects ** -** GAP handler for IsBound test on WP Object. Remember that bindings can +** GAP handler for IsBound test on WP object. Remember that bindings can ** evaporate in any garbage collection. */ - - Obj FuncIsBoundElmWPObj( Obj self, Obj wp, Obj pos) { return IsBoundElmWPObj(wp, pos) ? True : False; @@ -395,9 +403,9 @@ Obj FuncIsBoundElmWPObj( Obj self, Obj wp, Obj pos) /**************************************************************************** ** -*F FuncUnbindElmWPObj( , , ) . . . . . . . .Unbind WP Object +*F FuncUnbindElmWPObj(,,) . . . Unbind handler for WP objects ** -** GAP handler for Unbind on WP Object. +** GAP handler for Unbind on WP object. */ Obj FuncUnbindElmWPObj( Obj self, Obj wp, Obj pos) @@ -430,11 +438,11 @@ Obj FuncUnbindElmWPObj( Obj self, Obj wp, Obj pos) MEMBAR_READ(); if (ELM_WPOBJ(wp, ipos)) { if (IS_BAG_REF(tmp)) - FORGET_WP( &ELM_WPOBJ(wp, ipos)); - ELM_WPOBJ( wp, ipos) = 0; + FORGET_WP(wp, ipos); + SET_ELM_WPOBJ(wp, ipos, 0); } #else - ELM_WPOBJ( wp, ipos) = 0; + SET_ELM_WPOBJ(wp, ipos, 0); #endif } return 0; @@ -443,19 +451,10 @@ Obj FuncUnbindElmWPObj( Obj self, Obj wp, Obj pos) /**************************************************************************** ** -*F FuncElmWPObj( , , ) . . . . . . . . . . .Access WP Object +*F ElmDefWPList(,,) ** -** GAP handler for access to WP Object. If the entry is not bound, then fail -** is returned. It would not be correct to return an error, because there -** would be no way to safely access an element, which might evaporate -** between a call to IsBound and the access. This, of course, causes -** possible confusion with a WP object which does have a value of fail -** stored in it. This, however can be checked with a subsequent call to -** IsBound, relying on the fact that fail can never dissapear in a garbage -** collection. +** Provide implementation of 'ElmDefListFuncs'. */ - -// Provide implementation of ElmDefListFuncs Obj ElmDefWPList(Obj wp, Int ipos, Obj def) { GAP_ASSERT(TNUM_OBJ(wp) == T_WPOBJ); @@ -478,17 +477,26 @@ Obj ElmDefWPList(Obj wp, Int ipos, Obj def) if (elm == 0 || ELM_WPOBJ(wp, ipos) == 0) return def; #else - if (IS_WEAK_DEAD_BAG(elm)) - { - ELM_WPOBJ(wp,ipos) = 0; - return def; - } if (elm == 0) return def; #endif return elm; } + +/**************************************************************************** +** +*F FuncElmWPObj(,,) . . . . . . . access entry of a WP object +** +** GAP handler for access to WP object. If the entry is not bound, then fail +** is returned. It would not be correct to return an error, because there +** would be no way to safely access an element, which might evaporate +** between a call to IsBound and the access. This, of course, causes +** possible confusion with a WP object which does have a value of fail +** stored in it. This, however can be checked with a subsequent call to +** IsBound, relying on the fact that fail can never dissapear in a garbage +** collection. +*/ Obj FuncElmWPObj(Obj self, Obj wp, Obj pos) { if (TNUM_OBJ(wp) != T_WPOBJ) { @@ -513,10 +521,10 @@ Obj FuncElmWPObj(Obj self, Obj wp, Obj pos) /**************************************************************************** ** -*F TypeWPObj( ) . . . . . . . . . . . . . . . . . . . Type of WP Object +*F TypeWPObj() . . . . . . . . . . . . . . . . . . . . type of WP object ** -** This is imported from the library variable TYPE_WPOBJ. They all have the -** same type +** This returns the library variable TYPE_WPOBJ. All WP objects have the +** same type. */ Obj TYPE_WPOBJ; @@ -529,7 +537,7 @@ Obj TypeWPObj( Obj wp ) /**************************************************************************** ** -*F FuncIsWPObj( , ) . . . . . . . Handler for GAP function IsWPObj +*F FuncIsWPObj(,) . . . . . . . . handler for GAP function IsWPObj */ static Obj IsWPObjFilt; @@ -540,24 +548,25 @@ Obj FuncIsWPObj( Obj self, Obj wp) /**************************************************************************** ** -*F MarkWeakPointerObj( ) . . . . . . . . . . . . . . . Marking function -*F SweepWeakPointerObj( , , ) . . . . . . .Sweeping function +*F MarkWeakPointerObj() . . . . . . . . . . . . . . . . Marking function +*F SweepWeakPointerObj(,,) . . . . . . . . Sweeping function ** -** These functions are installed for GASMAN to use in garbage collection. The -** sweeping function must clean up any dead weak pointers encountered so -** that, after a full GC, the masterpointers occupied by the dead weak +** These functions are installed for GASMAN to use in garbage collection. +** The sweeping function must clean up any dead weak pointers encountered so +** that, after a full GC, the masterpointers occupied by the dead weak ** pointers can be reclaimed. */ #if defined(USE_GASMAN) -static void MarkWeakPointerObj( Obj wp) +static void MarkWeakPointerObj(Obj wp) { - Int i; - /* can't use the stored length here, in case we - are in the middle of copying */ - for (i = 1; i <= (SIZE_BAG(wp)/sizeof(Obj))-1; i++) - MarkBagWeakly(ELM_WPOBJ(wp,i)); + // can't use the stored length here, in case we are in the middle of + // copying + const UInt len = SIZE_BAG(wp) / sizeof(Obj) - 1; + for (UInt i = 1; i <= len; i++) { + MarkBagWeakly(ADDR_OBJ(wp)[i]); + } } static void SweepWeakPointerObj( Bag *src, Bag *dst, UInt len) @@ -599,7 +608,7 @@ void CopyWPObj(Obj copy, Obj original) if (IS_BAG_REF(tmp) && IS_BAG_REF(*ptr)) { *copyptr = ReplaceByCopy(tmp); #ifdef USE_BOEHM_GC - REGISTER_WP(copyptr, tmp); + GC_general_register_disappearing_link((void **)copyptr, tmp); #endif } ptr++; @@ -612,7 +621,7 @@ void CopyWPObj(Obj copy, Obj original) /**************************************************************************** ** -*F CopyObjWPObj( , ) . . . . . . . . . copy a positional object +*F CopyObjWPObj(,) . . . . . . . . . . . . . . . copy a WP object ** ** Note that an immutable copy of a weak pointer object is a normal ** immutable plist. An Immutable WP object is a contradiction. @@ -653,10 +662,13 @@ Obj CopyObjWPObj ( /* copy the subvalues */ for ( i = SIZE_OBJ(obj)/sizeof(Obj)-1; i > 0; i-- ) { - elm = CONST_ADDR_OBJ(obj)[i]; - if ( elm != 0 && !IS_WEAK_DEAD_BAG(elm)) { - tmp = COPY_OBJ( elm, mut ); - ADDR_OBJ(copy)[i] = tmp; + elm = ELM_WPOBJ(obj, i); + if (elm) { + tmp = COPY_OBJ(elm, mut); + if (mut) + SET_ELM_WPOBJ(copy, i, tmp); + else + SET_ELM_PLIST(copy, i, tmp); CHANGED_BAG( copy ); } } @@ -670,49 +682,61 @@ Obj CopyObjWPObj ( /**************************************************************************** ** -*F MakeImmutableWPObj( ) . . . . . . . . . . make immutable in place +*F MakeImmutableWPObj() . . . . . . . . . . . . make immutable in place ** */ void MakeImmutableWPObj( Obj obj ) { - UInt i; - #ifdef USE_BOEHM_GC + UInt i; UInt len = 0; - Obj copy = NewBag(T_PLIST+IMMUTABLE, SIZE_BAG(obj)); + Obj copy = NewBag(T_PLIST, SIZE_BAG(obj)); for (i = 1; i <= STORED_LEN_WPOBJ(obj); i++) { volatile Obj tmp = ELM_WPOBJ(obj, i); MEMBAR_READ(); - if (IS_BAG_REF(tmp)) { - if (ELM_WPOBJ(obj, i)) { - FORGET_WP(&ELM_WPOBJ(obj, i)); - len = i; + if (tmp) { + if (IS_BAG_REF(tmp) && ELM_WPOBJ(obj, i)) { + FORGET_WP(obj, i); } - } else { len = i; } SET_ELM_PLIST(copy, i, tmp); } SET_LEN_PLIST(copy, len); SET_PTR_BAG(obj, PTR_BAG(copy)); + + // Note: there is brief moment here where the WP obj has been turned into a + // mutable plist, but not yet been made immutable. This should be fine as + // long as the object is non-public, i.e., owned exclusively by the current + // thread. + #else - /* remove any weak dead bags */ - for (i = 1; i <= STORED_LEN_WPOBJ(obj); i++) { - Obj elm = ELM_WPOBJ(obj,i); - if (elm != 0 && IS_WEAK_DEAD_BAG(elm)) - ELM_WPOBJ(obj,i) = 0; - } - /* Change the type */ - RetypeBag( obj, T_PLIST+IMMUTABLE); + // recompute stored length + UInt len = LengthWPObj(obj); + + // remove any weak dead bags, by relying on side-effect of ELM_WPOBJ + for (UInt i = 1; i <= len; i++) { + ELM_WPOBJ(obj, i); + } + + // change the type - this works correctly, as the layout of weak pointer + // objects and plists is identical, and we removed all weak dead bags, + // and set the length properly. + RetypeBag(obj, (len == 0) ? T_PLIST_EMPTY : T_PLIST); #endif + + // make the plist immutable (and recursively any subobjects); note that + // this can cause garbage collections, hence we must do it after we + // completed conversion of the WP object into a plist + MakeImmutable(obj); } #if !defined(USE_THREADSAFE_COPYING) /**************************************************************************** ** -*F CleanObjWPObj( ) . . . . . . . . . . . . . . . . . . . clean WPobj +*F CleanObjWPObj() . . . . . . . . . . . . . . . . . . clean WP object */ void CleanObjWPObj ( Obj obj ) @@ -722,7 +746,7 @@ void CleanObjWPObj ( /**************************************************************************** ** -*F CopyObjWPObjCopy( , ) . . . . . . . . . . . copy a WPobj copy +*F CopyObjWPObjCopy(,) . . . . . . . . . . . copy a WP object copy */ Obj CopyObjWPObjCopy ( Obj obj, @@ -734,7 +758,7 @@ Obj CopyObjWPObjCopy ( /**************************************************************************** ** -*F CleanObjWPObjCopy( ) . . . . . . . . . . . . . . clean WPobj copy +*F CleanObjWPObjCopy() . . . . . . . . . . . . . . clean WP object copy */ void CleanObjWPObjCopy ( Obj obj ) @@ -751,9 +775,9 @@ void CleanObjWPObjCopy ( /* clean the subvalues */ for ( i = 1; i < SIZE_OBJ(obj)/sizeof(Obj); i++ ) { - elm = CONST_ADDR_OBJ(obj)[i]; - if ( elm != 0 && !IS_WEAK_DEAD_BAG(elm)) - CLEAN_OBJ( elm ); + elm = ELM_WPOBJ(obj, i); + if (elm) + CLEAN_OBJ(elm); } } @@ -763,46 +787,29 @@ void CleanObjWPObjCopy ( /**************************************************************************** ** -*F SaveWPObj( ) +*F SaveWPObj() */ -void SaveWPObj( Obj wpobj ) +void SaveWPObj(Obj wpobj) { - UInt len, i; - Obj *ptr; - Obj x; - ptr = ADDR_OBJ(wpobj)+1; - len = STORED_LEN_WPOBJ(wpobj); - SaveUInt(len); - for (i = 1; i <= len; i++) - { - x = *ptr; - if (IS_WEAK_DEAD_BAG(x)) - { - SaveSubObj(0); - *ptr = 0; - } - else - SaveSubObj(x); - ptr++; + UInt len = STORED_LEN_WPOBJ(wpobj); + SaveUInt(len); + for (UInt i = 1; i <= len; i++) { + SaveSubObj(ELM_WPOBJ(wpobj, i)); } } /**************************************************************************** ** -*F LoadWPObj( ) +*F LoadWPObj() */ -void LoadWPObj( Obj wpobj ) +void LoadWPObj(Obj wpobj) { - UInt len, i; - Obj *ptr; - ptr = ADDR_OBJ(wpobj)+1; - len = LoadUInt(); - STORE_LEN_WPOBJ(wpobj, len); - for (i = 1; i <= len; i++) - { - *ptr++ = LoadSubObj(); + const UInt len = LoadUInt(); + STORE_LEN_WPOBJ(wpobj, len); + for (UInt i = 1; i <= len; i++) { + SET_ELM_WPOBJ(wpobj, i, LoadSubObj()); } } @@ -844,7 +851,7 @@ static StructGVarFunc GVarFuncs [] = { /**************************************************************************** ** -*F InitKernel( ) . . . . . . . . initialise kernel data structures +*F InitKernel() . . . . . . . . . initialise kernel data structures */ static Int InitKernel ( StructInitInfo * module ) @@ -905,7 +912,7 @@ static Int InitKernel ( /**************************************************************************** ** -*F InitLibrary( ) . . . . . . . initialise library data structures +*F InitLibrary() . . . . . . . . initialise library data structures */ static Int InitLibrary ( StructInitInfo * module ) diff --git a/tst/testinstall/weakptr.tst b/tst/testinstall/weakptr.tst index e277d49f58..6e95615c75 100644 --- a/tst/testinstall/weakptr.tst +++ b/tst/testinstall/weakptr.tst @@ -75,14 +75,15 @@ true # gap> w[1]; 1 -gap> w{[2..4]} := [[1,2],E(5),311]; -[ [ 1, 2 ], E(5), 311 ] +gap> l := [ 311 ];; # keep ref so that this list is not garbage collected +gap> w{[2..4]} := [[1,2],E(5),l]; +[ [ 1, 2 ], E(5), [ 311 ] ] gap> Print(w,"\n"); -WeakPointerObj( [ 1, [ 1, 2 ], E(5), 311, , fail ] ) +WeakPointerObj( [ 1, [ 1, 2 ], E(5), [ 311 ], , fail ] ) gap> Print(StructuralCopy(w),"\n"); -WeakPointerObj( [ 1, [ 1, 2 ], E(5), 311, , fail ] ) +WeakPointerObj( [ 1, [ 1, 2 ], E(5), [ 311 ], , fail ] ) gap> Immutable(w); -[ 1, [ 1, 2 ], E(5), 311,, fail ] +[ 1, [ 1, 2 ], E(5), [ 311 ],, fail ] gap> IsBound(w[2]); true gap> GASMAN("collect"); @@ -90,13 +91,38 @@ gap> IsBound(w[5]); false gap> Unbind(w[2]); gap> Print(w,"\n"); -WeakPointerObj( [ 1, , E(5), 311, , fail ] ) +WeakPointerObj( [ 1, , E(5), [ 311 ], , fail ] ) gap> Immutable(w); -[ 1,, E(5), 311,, fail ] +[ 1,, E(5), [ 311 ],, fail ] gap> w; -WeakPointerObj( [ 1, , E(5), 311, , fail ] ) +WeakPointerObj( [ 1, , E(5), [ 311 ], , fail ] ) gap> MakeImmutable(w); -[ 1,, E(5), 311,, fail ] +[ 1,, E(5), [ 311 ],, fail ] gap> w; -[ 1,, E(5), 311,, fail ] +[ 1,, E(5), [ 311 ],, fail ] +gap> IsMutable(w); +false +gap> ForAny(w, IsMutable); +false + +# +# test recursive MakeImmutable +# +gap> w := WeakPointerObj([ ~ ]);; +gap> MakeImmutable(w); +[ [ ~[1] ] ] + +# +gap> w := WeakPointerObj([ 1 ]);; +gap> w[1] := w;; +gap> MakeImmutable(w); +[ ~ ] + +# +gap> w := WeakPointerObj([ rec() ]);; +gap> w[1].self := w;; +gap> MakeImmutable(w); +[ rec( self := ~ ) ] + +# gap> STOP_TEST( "weakptr.tst", 1);