Index: generic/nsf.c =================================================================== diff -u -r5163190ade6f6a2abcd8b7f0265f74457557a61c -r36b29a9f1f308d692dc1b4ce35c4adb0948bd6bd --- generic/nsf.c (.../nsf.c) (revision 5163190ade6f6a2abcd8b7f0265f74457557a61c) +++ generic/nsf.c (.../nsf.c) (revision 36b29a9f1f308d692dc1b4ce35c4adb0948bd6bd) @@ -427,7 +427,6 @@ static int MethodSourceMatches(int withSource, NsfClass *cl, NsfObject *object); static NsfObjectOpt *NsfRequireObjectOpt(NsfObject *object) nonnull(1) returns_nonnull; -static NsfClassOpt * NsfRequireClassOpt(/*@notnull@*/ NsfClass *cl) nonnull(1) returns_nonnull; static int ObjectSystemsCheckSystemMethod(Tcl_Interp *interp, CONST char *methodName, NsfObject *object, unsigned int flags) @@ -4148,7 +4147,7 @@ } -static NsfClassOpt * +NsfClassOpt * NsfRequireClassOpt(/*@notnull@*/ NsfClass *cl) { assert(cl); @@ -18724,16 +18723,24 @@ } } - if (clopt) { + if (clopt != NULL) { /* * Remove this class from all isClassMixinOf lists and clear the * class mixin list */ - if (clopt->classMixins) RemoveFromClassMixinsOf(clopt->id, clopt->classMixins); + if (clopt->classMixins) { + RemoveFromClassMixinsOf(clopt->id, clopt->classMixins); + } CmdListFree(&clopt->classMixins, GuardDel); CmdListFree(&clopt->classFilters, GuardDel); + if (clopt->mixinRegObjs != NULL) { + NsfMixinregInvalidate(interp, clopt->mixinRegObjs); + DECR_REF_COUNT2("mixinRegObjs", clopt->mixinRegObjs); + clopt->mixinRegObjs = NULL; + } + if (!recreate) { /* * Remove this class from all mixin lists and clear the isObjectMixinOf list @@ -18805,9 +18812,9 @@ MEM_COUNT_FREE("Tcl_InitHashTable", &cl->instances); } - if ((clopt) && (!recreate)) { + if (clopt != NULL && recreate == 0) { FREE(NsfClassOpt, clopt); - cl->opt = 0; + cl->opt = NULL; } if (subClasses) { @@ -26770,8 +26777,8 @@ int canFree; } NsfParamWrapper; -static Tcl_DupInternalRepProc ParamDupInteralRep; -static Tcl_FreeInternalRepProc ParamFreeInternalRep; +static Tcl_DupInternalRepProc ParamDupInteralRep; +static Tcl_FreeInternalRepProc ParamFreeInternalRep; static Tcl_UpdateStringProc ParamUpdateString; static void ParamUpdateString(Tcl_Obj *objPtr) nonnull(1); Index: generic/nsfInt.h =================================================================== diff -u -r15beef03245b7fe339e4bd22cc8ee5da92d789a6 -r36b29a9f1f308d692dc1b4ce35c4adb0948bd6bd --- generic/nsfInt.h (.../nsfInt.h) (revision 15beef03245b7fe339e4bd22cc8ee5da92d789a6) +++ generic/nsfInt.h (.../nsfInt.h) (revision 36b29a9f1f308d692dc1b4ce35c4adb0948bd6bd) @@ -564,6 +564,7 @@ NsfCmdList *isObjectMixinOf; NsfCmdList *isClassMixinOf; NsfAssertionStore *assertions; + Tcl_Obj *mixinRegObjs; #ifdef NSF_OBJECTDATA Tcl_HashTable *objectdata; #endif @@ -716,13 +717,18 @@ /* obj types */ EXTERN Tcl_ObjType NsfMixinregObjType; -int NsfMixinregGet(Tcl_Interp *interp, Tcl_Obj *obj, NsfClass **clPtr, Tcl_Obj **guardObj) +EXTERN int NsfMixinregGet(Tcl_Interp *interp, Tcl_Obj *obj, NsfClass **clPtr, Tcl_Obj **guardObj) nonnull(1) nonnull(2) nonnull(3) nonnull(4); +EXTERN int NsfMixinregInvalidate(Tcl_Interp *interp, Tcl_Obj *obj) + nonnull(1) nonnull(2); EXTERN Tcl_ObjType NsfFilterregObjType; -int NsfFilterregGet(Tcl_Interp *interp, Tcl_Obj *obj, Tcl_Obj **filterObj, Tcl_Obj **guardObj) +EXTERN int NsfFilterregGet(Tcl_Interp *interp, Tcl_Obj *obj, Tcl_Obj **filterObj, Tcl_Obj **guardObj) nonnull(1) nonnull(2) nonnull(3) nonnull(4); +EXTERN NsfClassOpt *NsfRequireClassOpt(/*@notnull@*/ NsfClass *cl) nonnull(1) returns_nonnull; + + /* Next Scripting ShadowTclCommands */ typedef struct NsfShadowTclCommandInfo { TclObjCmdProcType proc; Index: generic/nsfObj.c =================================================================== diff -u -r5163190ade6f6a2abcd8b7f0265f74457557a61c -r36b29a9f1f308d692dc1b4ce35c4adb0948bd6bd --- generic/nsfObj.c (.../nsfObj.c) (revision 5163190ade6f6a2abcd8b7f0265f74457557a61c) +++ generic/nsfObj.c (.../nsfObj.c) (revision 36b29a9f1f308d692dc1b4ce35c4adb0948bd6bd) @@ -350,7 +350,7 @@ { Mixinreg *mixinRegPtr = (Mixinreg *)objPtr->internalRep.twoPtrValue.ptr1; - assert(mixinRegPtr); + assert(mixinRegPtr != NULL); /*fprintf(stderr, "MixinregFreeInternalRep freeing mixinReg %p class %p guard %p refcount before decr %d\n", mixinRegPtr, mixinRegPtr->mixin, mixinRegPtr->guardObj, (&(mixinRegPtr->mixin)->object)->refCount);*/ @@ -365,6 +365,8 @@ * ... and free structure */ FREE(Mixinreg, mixinRegPtr); + objPtr->internalRep.twoPtrValue.ptr1 = NULL; + objPtr->typePtr = NULL; } /* @@ -405,8 +407,8 @@ */ static int MixinregSetFromAny( - Tcl_Interp *interp, /* Used for error reporting if not NULL. */ - register Tcl_Obj *objPtr) /* The object to convert. */ + Tcl_Interp *interp, /* Used for error reporting if not NULL. */ + Tcl_Obj *objPtr) /* The object to convert. */ { NsfClass *mixin = NULL; Tcl_Obj *guardObj = NULL, *nameObj = NULL; @@ -455,6 +457,18 @@ NsfObjectRefCountIncr((&mixin->object)); if (guardObj) {INCR_REF_COUNT2("mixinRegPtr->guardObj", guardObj);} + /* + * Build list of tcl-objs per mixin class for invalidation. + */ + { NsfClassOpt *clOpt = NsfRequireClassOpt(mixin); + if (clOpt->mixinRegObjs == NULL) { + clOpt->mixinRegObjs = Tcl_NewListObj(1, &objPtr); + INCR_REF_COUNT2("mixinRegObjs", clOpt->mixinRegObjs); + } else { + Tcl_ListObjAppendElement(interp, clOpt->mixinRegObjs, objPtr); + } + } + /*fprintf(stderr, "MixinregSetFromAny alloc mixinReg %p class %p guard %p object->refCount %d\n", mixinRegPtr, mixinRegPtr->mixin, mixinRegPtr->guardObj, ((&mixin->object)->refCount));*/ @@ -507,7 +521,8 @@ /* * The cmd is deleted. retry to refetch it. */ - /*fprintf(stderr, "... we have to refetch \n");*/ + /*fprintf(stderr, "### we have to refetch internal rep of obj %p refCount %d\n", + obj, obj->refCount);*/ if (MixinregSetFromAny(interp, obj) == TCL_OK) { mixinRegPtr = obj->internalRep.twoPtrValue.ptr1; @@ -528,6 +543,41 @@ /* *---------------------------------------------------------------------- * + * NsfMixinregInvalidate -- + * + * MixinClasses keep a list of Tcl_Objs of type mixinReg. + * When a class is deleted, this call makes sure, that + * non-of these have th chance to point to a stale entry. + * + * Results: + * Tcl result code + * + * Side effects: + * Freeing internal rep of Tcl_Objs. + * + *---------------------------------------------------------------------- + */ + +int +NsfMixinregInvalidate(Tcl_Interp *interp, Tcl_Obj *obj) { + int i, result, oc = 0; + Tcl_Obj **objv; + + result = Tcl_ListObjGetElements(interp, obj, &oc, &objv); + + for (i= 0; i < oc; i++) { + if (objv[i]->typePtr == &NsfMixinregObjType) { + MixinregFreeInternalRep((objv[i])); + } + } + + return result; +} + + +/* + *---------------------------------------------------------------------- + * * Filterreg Tcl_Obj type -- * * The filter registration type is an Tcl_Obj type carrying a the @@ -584,6 +634,8 @@ * ... and free structure */ FREE(Filterreg, filterregPtr); + objPtr->internalRep.twoPtrValue.ptr1 = NULL; + objPtr->typePtr = NULL; } /*