Tcl Source Code

Artifact [5ea56d369f]
Login

Artifact 5ea56d369f9fd92cca76d381aa7ad17379c27d93:

Attachment "signalDeletion.patch" to ticket [1512138fff] added by msofer 2006-10-01 02:01:58.
Index: generic/tclInt.decls
===================================================================
RCS file: /cvsroot/tcl/tcl/generic/tclInt.decls,v
retrieving revision 1.97
diff -u -r1.97 tclInt.decls
--- generic/tclInt.decls	21 Jun 2006 03:10:39 -0000	1.97
+++ generic/tclInt.decls	30 Sep 2006 18:55:26 -0000
@@ -890,6 +890,10 @@
 	    int keyc, Tcl_Obj *CONST keyv[], int flags)
 }
 
+declare 226 generic {
+    int TclObjBeingDeleted(Tcl_Obj *objPtr)
+}
+
 ##############################################################################
 
 # Define the platform specific internal Tcl interface. These functions are
Index: generic/tclInt.h
===================================================================
RCS file: /cvsroot/tcl/tcl/generic/tclInt.h,v
retrieving revision 1.278
diff -u -r1.278 tclInt.h
--- generic/tclInt.h	30 Sep 2006 17:56:47 -0000	1.278
+++ generic/tclInt.h	30 Sep 2006 18:55:28 -0000
@@ -2646,15 +2646,20 @@
     (objPtr)->length   = 0; \
     (objPtr)->typePtr  = NULL
 
+/* Invalidate the string rep first so we can use the bytes value \
+ * for our pointer chain, and signal an obj deletion (as opposed \
+ * to shimmering) with 'length == -1' */ \
+
 # define TclDecrRefCount(objPtr) \
     if (--(objPtr)->refCount <= 0) { \
 	if ((objPtr)->typePtr && (objPtr)->typePtr->freeIntRepProc) { \
 	    TclFreeObj(objPtr); \
 	} else { \
-	    if ((objPtr)->bytes \
-		    && ((objPtr)->bytes != tclEmptyStringRep)) { \
-		ckfree((char *) (objPtr)->bytes); \
+  	    if ((objPtr)->bytes \
+	            && ((objPtr)->bytes != tclEmptyStringRep)) { \
+	        ckfree((char *) (objPtr)->bytes); \
 	    } \
+            (objPtr)->length = -1; \
 	    TclFreeObjStorage(objPtr); \
 	    TclIncrObjsFreed(); \
 	} \
Index: generic/tclIntDecls.h
===================================================================
RCS file: /cvsroot/tcl/tcl/generic/tclIntDecls.h,v
retrieving revision 1.87
diff -u -r1.87 tclIntDecls.h
--- generic/tclIntDecls.h	21 Jun 2006 03:10:39 -0000	1.87
+++ generic/tclIntDecls.h	30 Sep 2006 18:55:28 -0000
@@ -1020,6 +1020,11 @@
 				Tcl_Obj * rootPtr, int keyc, 
 				Tcl_Obj *CONST keyv[], int flags));
 #endif
+#ifndef TclObjBeingDeleted_TCL_DECLARED
+#define TclObjBeingDeleted_TCL_DECLARED
+/* 226 */
+EXTERN int		TclObjBeingDeleted _ANSI_ARGS_((Tcl_Obj * objPtr));
+#endif
 
 typedef struct TclIntStubs {
     int magic;
@@ -1266,6 +1271,7 @@
     void *reserved223;
     TclPlatformType * (*tclGetPlatform) _ANSI_ARGS_((void)); /* 224 */
     Tcl_Obj * (*tclTraceDictPath) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Obj * rootPtr, int keyc, Tcl_Obj *CONST keyv[], int flags)); /* 225 */
+    int (*tclObjBeingDeleted) _ANSI_ARGS_((Tcl_Obj * objPtr)); /* 226 */
 } TclIntStubs;
 
 #ifdef __cplusplus
@@ -1955,6 +1961,10 @@
 #define TclTraceDictPath \
 	(tclIntStubsPtr->tclTraceDictPath) /* 225 */
 #endif
+#ifndef TclObjBeingDeleted
+#define TclObjBeingDeleted \
+	(tclIntStubsPtr->tclObjBeingDeleted) /* 226 */
+#endif
 
 #endif /* defined(USE_TCL_STUBS) && !defined(USE_TCL_STUB_PROCS) */
 
Index: generic/tclObj.c
===================================================================
RCS file: /cvsroot/tcl/tcl/generic/tclObj.c,v
retrieving revision 1.112
diff -u -r1.112 tclObj.c
--- generic/tclObj.c	10 Aug 2006 12:15:31 -0000	1.112
+++ generic/tclObj.c	30 Sep 2006 18:55:30 -0000
@@ -111,13 +111,8 @@
 #define ObjDeletePending(contextPtr)	((contextPtr)->deletionCount > 0)
 #define ObjOnStack(contextPtr)		((contextPtr)->deletionStack != NULL)
 #define PushObjToDelete(contextPtr,objPtr) \
-    /* Invalidate the string rep first so we can use the bytes value \
-     * for our pointer chain. */ \
-    if (((objPtr)->bytes != NULL) \
-	    && ((objPtr)->bytes != tclEmptyStringRep)) { \
-	ckfree((char *) (objPtr)->bytes); \
-    } \
-    /* Now push onto the head of the stack. */ \
+    /* The string rep is already invalidated so we can use the bytes value \
+     * for our pointer chain: push onto the head of the stack. */ \
     (objPtr)->bytes = (char *) ((contextPtr)->deletionStack); \
     (contextPtr)->deletionStack = (objPtr)
 #define PopObjToDelete(contextPtr,objPtrVar) \
@@ -849,6 +844,13 @@
 	Tcl_Panic("Reference count for %lx was negative", objPtr);
     }
 
+    /* Invalidate the string rep first so we can use the bytes value 
+     * for our pointer chain, and signal an obj deletion (as opposed
+     * to shimmering) with 'length == -1' */ 
+    
+    TclInvalidateStringRep(objPtr);
+    objPtr->length = -1;
+
     if (ObjDeletePending(context)) {
 	PushObjToDelete(context, objPtr);
     } else {
@@ -857,7 +859,6 @@
 	    typePtr->freeIntRepProc(objPtr);
 	    ObjDeletionUnlock(context);
 	}
-	TclInvalidateStringRep(objPtr);
 
 	Tcl_MutexLock(&tclObjMutex);
 	ckfree((char *) objPtr);
@@ -888,15 +889,19 @@
 TclFreeObj(
     register Tcl_Obj *objPtr)	/* The object to be freed. */
 {
+    /* Invalidate the string rep first so we can use the bytes value 
+     * for our pointer chain, and signal an obj deletion (as opposed
+     * to shimmering) with 'length == -1' */ 
+
+    TclInvalidateStringRep(objPtr);
+    objPtr->length = -1;
+    
     if (!objPtr->typePtr || !objPtr->typePtr->freeIntRepProc) {
 	/*
 	 * objPtr can be freed safely, as it will not attempt to free any
 	 * other objects: it will not cause recursive calls to this function.
 	 */
 
-	if (objPtr->bytes && (objPtr->bytes != tclEmptyStringRep)) {
-	    ckfree((char *) objPtr->bytes);
-	}
 	TclFreeObjStorage(objPtr);
 	TclIncrObjsFreed();
     } else {
@@ -923,9 +928,6 @@
 	    objPtr->typePtr->freeIntRepProc(objPtr);
 	    ObjDeletionUnlock(context);
 
-	    if (objPtr->bytes && (objPtr->bytes != tclEmptyStringRep)) {
-		ckfree((char *) objPtr->bytes);
-	    }
 	    TclFreeObjStorage(objPtr);
 	    TclIncrObjsFreed();
 	    ObjDeletionLock(context);
@@ -948,6 +950,31 @@
 /*
  *----------------------------------------------------------------------
  *
+ * TclObjBeingDeleted --
+ *
+ *	This function returns 1 when the Tcl_Obj is being deleted. It is
+ *	provided for the rare cases where the reason for the loss of an
+ *	internal rep might be relevant [FR 1512138]
+ *
+ * Results:
+ *	1 if being deleted, 0 otherwise.
+ *
+ * Side effects:
+ *	None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TclObjBeingDeleted(Tcl_Obj *objPtr)
+{
+    return (objPtr->length == -1);
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
  * Tcl_DuplicateObj --
  *
  *	Create and return a new object that is a duplicate of the argument
Index: generic/tclStubInit.c
===================================================================
RCS file: /cvsroot/tcl/tcl/generic/tclStubInit.c,v
retrieving revision 1.132
diff -u -r1.132 tclStubInit.c
--- generic/tclStubInit.c	22 Sep 2006 18:13:29 -0000	1.132
+++ generic/tclStubInit.c	30 Sep 2006 18:55:32 -0000
@@ -317,6 +317,7 @@
     NULL, /* 223 */
     TclGetPlatform, /* 224 */
     TclTraceDictPath, /* 225 */
+    TclObjBeingDeleted, /* 226 */
 };
 
 TclIntPlatStubs tclIntPlatStubs = {