summaryrefslogtreecommitdiffstats
path: root/generic/tclOO.c
diff options
context:
space:
mode:
Diffstat (limited to 'generic/tclOO.c')
-rw-r--r--generic/tclOO.c211
1 files changed, 112 insertions, 99 deletions
diff --git a/generic/tclOO.c b/generic/tclOO.c
index dcf48ef..c80f039 100644
--- a/generic/tclOO.c
+++ b/generic/tclOO.c
@@ -523,47 +523,47 @@ InitClassSystemRoots(
fakeCls.thisPtr = &fakeObject;
+
fPtr->objectCls = AllocClass(interp,
AllocObject(interp, "object", (Namespace *)fPtr->ooNs, NULL));
- fPtr->classCls = AllocClass(interp,
- AllocObject(interp, "class", (Namespace *)fPtr->ooNs, NULL));
-
- /*
- * Rewire bootstrapped objects.
- */
-
- fPtr->objectCls->thisPtr->selfCls = fPtr->classCls;
- fPtr->classCls->thisPtr->selfCls = fPtr->classCls;
-
+ /* Corresponding TclOODecrRefCount in KillFoudation */
AddRef(fPtr->objectCls->thisPtr);
- AddRef(fPtr->classCls->thisPtr);
- AddRef(fPtr->classCls->thisPtr->selfCls->thisPtr);
- AddRef(fPtr->objectCls->thisPtr->selfCls->thisPtr);
- /*
- * Special initialization for the primordial objects.
- */
+ /* This is why it is unnecessary in this routine to replace the
+ * incremented reference count of fPtr->objectCls that was swallowed by
+ * fakeObject. */
+ fPtr->objectCls->superclasses.num = 0;
+ ckfree(fPtr->objectCls->superclasses.list);
+ fPtr->objectCls->superclasses.list = NULL;
+ /* special initialization for the primordial objects */
fPtr->objectCls->thisPtr->flags |= ROOT_OBJECT;
fPtr->objectCls->flags |= ROOT_OBJECT;
+ fPtr->classCls = AllocClass(interp,
+ AllocObject(interp, "class", (Namespace *)fPtr->ooNs, NULL));
+ /* Corresponding TclOODecrRefCount in KillFoudation */
+ AddRef(fPtr->classCls->thisPtr);
+
/*
- * This is why it is unnecessary in this routine to make up for the
- * incremented reference count of fPtr->objectCls that was sallwed by
- * fakeObject.
+ * Increment reference counts for each reference because these
+ * relationships can be dynamically changed.
+ *
+ * Corresponding TclOODecrRefCount for all incremented refcounts is in
+ * KillFoundation.
*/
- fPtr->objectCls->superclasses.num = 0;
- ckfree(fPtr->objectCls->superclasses.list);
- fPtr->objectCls->superclasses.list = NULL;
+ /* Rewire bootstrapped objects. */
+ fPtr->objectCls->thisPtr->selfCls = fPtr->classCls;
+ AddRef(fPtr->objectCls->thisPtr->selfCls->thisPtr);
+
+ fPtr->classCls->thisPtr->selfCls = fPtr->classCls;
+ AddRef(fPtr->classCls->thisPtr->selfCls->thisPtr);
fPtr->classCls->thisPtr->flags |= ROOT_CLASS;
fPtr->classCls->flags |= ROOT_CLASS;
- /*
- * Standard initialization for new Objects.
- */
-
+ /* Standard initialization for new Objects */
TclOOAddToInstances(fPtr->objectCls->thisPtr, fPtr->classCls);
TclOOAddToInstances(fPtr->classCls->thisPtr, fPtr->classCls);
TclOOAddToSubclasses(fPtr->classCls, fPtr->objectCls);
@@ -632,20 +632,20 @@ KillFoundation(
{
Foundation *fPtr = GetFoundation(interp);
- /*
- * Crude mechanism to avoid leaking the Object struct of the
- * foundation components oo::object and oo::class
- *
- * Should probably be replaced with something more elegantly designed.
- */
- while (TclOODecrRefCount(fPtr->objectCls->thisPtr) == 0) {};
- while (TclOODecrRefCount(fPtr->classCls->thisPtr) == 0) {};
-
TclDecrRefCount(fPtr->unknownMethodNameObj);
TclDecrRefCount(fPtr->constructorName);
TclDecrRefCount(fPtr->destructorName);
TclDecrRefCount(fPtr->clonedName);
TclDecrRefCount(fPtr->defineName);
+ if (fPtr->objectCls->thisPtr->selfCls != NULL) {
+ TclOODecrRefCount(fPtr->objectCls->thisPtr->selfCls->thisPtr);
+ }
+ if (fPtr->classCls->thisPtr->selfCls != NULL) {
+ TclOODecrRefCount(fPtr->classCls->thisPtr->selfCls->thisPtr);
+ }
+ TclOODecrRefCount(fPtr->objectCls->thisPtr);
+ TclOODecrRefCount(fPtr->classCls->thisPtr);
+
ckfree(fPtr);
}
@@ -729,6 +729,8 @@ AllocObject(
Tcl_ResetResult(interp);
}
+ ((Namespace *)oPtr->namespacePtr)->refCount++;
+
/*
* Make the namespace know about the helper commands. This grants access
* to the [self] and [next] commands.
@@ -901,10 +903,9 @@ ObjectRenamedTrace(
/*
* ----------------------------------------------------------------------
*
- * DeleteDescendants, ReleaseClassContents --
+ * DeleteDescendants --
*
- * Tear down the special class data structure, including deleting all
- * dependent classes and objects.
+ * Delete all descendants of a particular class.
*
* ----------------------------------------------------------------------
*/
@@ -916,44 +917,55 @@ DeleteDescendants(
{
Class *clsPtr = oPtr->classPtr, *subclassPtr, *mixinSubclassPtr;
Object *instancePtr;
- int i;
/*
* Squelch classes that this class has been mixed into.
*/
- FOREACH(mixinSubclassPtr, clsPtr->mixinSubs) {
- /*
- * This condition also covers the case where mixinSubclassPtr ==
- * clsPtr
- */
-
- if (!Deleted(mixinSubclassPtr->thisPtr)) {
- Tcl_DeleteCommandFromToken(interp,
- mixinSubclassPtr->thisPtr->command);
+ if (clsPtr->mixinSubs.num > 0) {
+ while (clsPtr->mixinSubs.num > 0) {
+ mixinSubclassPtr = clsPtr->mixinSubs.list[clsPtr->mixinSubs.num-1];
+ /* This condition also covers the case where mixinSubclassPtr ==
+ * clsPtr
+ */
+ if (!Deleted(mixinSubclassPtr->thisPtr)) {
+ Tcl_DeleteCommandFromToken(interp,
+ mixinSubclassPtr->thisPtr->command);
+ }
+ TclOORemoveFromMixinSubs(mixinSubclassPtr, clsPtr);
}
- i -= TclOORemoveFromMixinSubs(mixinSubclassPtr, clsPtr);
- TclOODecrRefCount(mixinSubclassPtr->thisPtr);
+ }
+ if (clsPtr->mixinSubs.size > 0) {
+ ckfree(clsPtr->mixinSubs.list);
+ clsPtr->mixinSubs.size = 0;
}
/*
* Squelch subclasses of this class.
*/
- FOREACH(subclassPtr, clsPtr->subclasses) {
- if (!Deleted(subclassPtr->thisPtr) && !IsRoot(subclassPtr)) {
- Tcl_DeleteCommandFromToken(interp, subclassPtr->thisPtr->command);
+ if (clsPtr->subclasses.num > 0) {
+ while (clsPtr->subclasses.num > 0) {
+ subclassPtr = clsPtr->subclasses.list[clsPtr->subclasses.num-1];
+ if (!Deleted(subclassPtr->thisPtr) && !IsRoot(subclassPtr)) {
+ Tcl_DeleteCommandFromToken(interp, subclassPtr->thisPtr->command);
+ }
+ TclOORemoveFromSubclasses(subclassPtr, clsPtr);
}
- i -= TclOORemoveFromSubclasses(subclassPtr, clsPtr);
- TclOODecrRefCount(subclassPtr->thisPtr);
+ }
+ if (clsPtr->subclasses.size > 0) {
+ ckfree(clsPtr->subclasses.list);
+ clsPtr->subclasses.list = NULL;
+ clsPtr->subclasses.size = 0;
}
/*
* Squelch instances of this class (includes objects we're mixed into).
*/
- if (!IsRootClass(oPtr)) {
- FOREACH(instancePtr, clsPtr->instances) {
+ if (clsPtr->instances.num > 0) {
+ while (clsPtr->instances.num > 0) {
+ instancePtr = clsPtr->instances.list[clsPtr->instances.num-1];
/*
* This condition also covers the case where instancePtr == oPtr
*/
@@ -961,10 +973,26 @@ DeleteDescendants(
if (!Deleted(instancePtr) && !IsRoot(instancePtr)) {
Tcl_DeleteCommandFromToken(interp, instancePtr->command);
}
- i -= TclOORemoveFromInstances(instancePtr, clsPtr);
+ TclOORemoveFromInstances(instancePtr, clsPtr);
}
}
+ if (clsPtr->instances.size > 0) {
+ ckfree(clsPtr->instances.list);
+ clsPtr->instances.list = NULL;
+ clsPtr->instances.size = 0;
+ }
}
+
+/*
+ * ----------------------------------------------------------------------
+ *
+ * ReleaseClassContents --
+ *
+ * Tear down the special class data structure, including deleting all
+ * dependent classes and objects.
+ *
+ * ----------------------------------------------------------------------
+ */
static void
ReleaseClassContents(
@@ -1034,21 +1062,6 @@ ReleaseClassContents(
}
/*
- * Squelch our instances.
- */
-
- if (clsPtr->instances.num) {
- Object *oPtr;
-
- FOREACH(oPtr, clsPtr->instances) {
- TclOODecrRefCount(oPtr);
- }
- ckfree(clsPtr->instances.list);
- clsPtr->instances.list = NULL;
- clsPtr->instances.num = 0;
- }
-
- /*
* Squelch our metadata.
*/
@@ -1064,11 +1077,21 @@ ReleaseClassContents(
clsPtr->metadataPtr = NULL;
}
- FOREACH(tmpClsPtr, clsPtr->mixins) {
- TclOORemoveFromMixinSubs(clsPtr, tmpClsPtr);
+ if (clsPtr->mixins.num) {
+ FOREACH(tmpClsPtr, clsPtr->mixins) {
+ TclOORemoveFromMixinSubs(clsPtr, tmpClsPtr);
+ }
+ ckfree(clsPtr->mixins.list);
}
- FOREACH(tmpClsPtr, clsPtr->superclasses) {
- TclOORemoveFromSubclasses(clsPtr, tmpClsPtr);
+
+ if (clsPtr->superclasses.num > 0) {
+ FOREACH(tmpClsPtr, clsPtr->superclasses) {
+ TclOORemoveFromSubclasses(clsPtr, tmpClsPtr);
+ TclOODecrRefCount(tmpClsPtr->thisPtr);
+ }
+ ckfree(clsPtr->superclasses.list);
+ clsPtr->superclasses.num = 0;
+ clsPtr->superclasses.list = NULL;
}
FOREACH_HASH_VALUE(mPtr, &clsPtr->classMethods) {
@@ -1204,10 +1227,10 @@ ObjectNamespaceDeleted(
TclOORemoveFromInstances(oPtr, oPtr->selfCls);
- FOREACH(mixinPtr, oPtr->mixins) {
- i -= TclOORemoveFromInstances(oPtr, mixinPtr);
- }
- if (i) {
+ if (oPtr->mixins.num > 0) {
+ FOREACH(mixinPtr, oPtr->mixins) {
+ TclOORemoveFromInstances(oPtr, mixinPtr);
+ }
ckfree(oPtr->mixins.list);
}
@@ -1276,7 +1299,9 @@ ObjectNamespaceDeleted(
* Delete the object structure itself.
*/
+ TclNsDecrRefCount((Namespace *)oPtr->namespacePtr);
oPtr->namespacePtr = NULL;
+ TclOODecrRefCount(oPtr->selfCls->thisPtr);
oPtr->selfCls = NULL;
TclOODecrRefCount(oPtr);
return;
@@ -1299,14 +1324,8 @@ TclOODecrRefCount(
Object *oPtr)
{
if (oPtr->refCount-- <= 1) {
- Class *clsPtr = oPtr->classPtr;
if (oPtr->classPtr != NULL) {
- ckfree(clsPtr->superclasses.list);
- ckfree(clsPtr->subclasses.list);
- ckfree(clsPtr->instances.list);
- ckfree(clsPtr->mixinSubs.list);
- ckfree(clsPtr->mixins.list);
ckfree(oPtr->classPtr);
}
ckfree(oPtr);
@@ -1335,10 +1354,6 @@ TclOORemoveFromInstances(
int i, res = 0;
Object *instPtr;
- if (Deleted(clsPtr->thisPtr)) {
- return res;
- }
-
FOREACH(instPtr, clsPtr->instances) {
if (oPtr == instPtr) {
RemoveItem(Object, clsPtr->instances, i);
@@ -1401,10 +1416,6 @@ TclOORemoveFromSubclasses(
int i, res = 0;
Class *subclsPtr;
- if (Deleted(superPtr->thisPtr)) {
- return res;
- }
-
FOREACH(subclsPtr, superPtr->subclasses) {
if (subPtr == subclsPtr) {
RemoveItem(Class, superPtr->subclasses, i);
@@ -1469,10 +1480,6 @@ TclOORemoveFromMixinSubs(
int i, res = 0;
Class *subclsPtr;
- if (Deleted(superPtr->thisPtr)) {
- return res;
- }
-
FOREACH(subclsPtr, superPtr->mixinSubs) {
if (subPtr == subclsPtr) {
RemoveItem(Class, superPtr->mixinSubs, i);
@@ -1780,6 +1787,7 @@ TclNewObjectInstanceCommon(
oPtr = AllocObject(interp, simpleName, nsPtr, nsNameStr);
oPtr->selfCls = classPtr;
+ AddRef(classPtr->thisPtr);
TclOOAddToInstances(oPtr, classPtr);
/*
@@ -2025,6 +2033,11 @@ Tcl_CopyObjectInstance(
cls2Ptr->superclasses.num = clsPtr->superclasses.num;
FOREACH(superPtr, cls2Ptr->superclasses) {
TclOOAddToSubclasses(cls2Ptr, superPtr);
+
+ /* For the new item in cls2Ptr->superclasses that memcpy just
+ * created
+ */
+ AddRef(superPtr->thisPtr);
}
/*