diff options
Diffstat (limited to 'generic/tclAsync.c')
-rw-r--r-- | generic/tclAsync.c | 62 |
1 files changed, 46 insertions, 16 deletions
diff --git a/generic/tclAsync.c b/generic/tclAsync.c index 5c3a535..14804e4 100644 --- a/generic/tclAsync.c +++ b/generic/tclAsync.c @@ -10,8 +10,6 @@ * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. - * - * RCS: @(#) $Id: tclAsync.c,v 1.9 2005/11/07 15:19:29 dkf Exp $ */ #include "tclInt.h" @@ -120,7 +118,7 @@ Tcl_AsyncCreate( AsyncHandler *asyncPtr; ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); - asyncPtr = (AsyncHandler *) ckalloc(sizeof(AsyncHandler)); + asyncPtr = ckalloc(sizeof(AsyncHandler)); asyncPtr->ready = 0; asyncPtr->nextPtr = NULL; asyncPtr->proc = proc; @@ -237,7 +235,7 @@ Tcl_AsyncInvoke( } asyncPtr->ready = 0; Tcl_MutexUnlock(&tsdPtr->asyncMutex); - code = (*asyncPtr->proc)(asyncPtr->clientData, interp, code); + code = asyncPtr->proc(asyncPtr->clientData, interp, code); Tcl_MutexLock(&tsdPtr->asyncMutex); } tsdPtr->asyncActive = 0; @@ -259,6 +257,13 @@ Tcl_AsyncInvoke( * Side effects: * The state associated with the handler is deleted. * + * Failure to locate the handler in current thread private list + * of async handlers will result in panic; exception: the list + * is already empty (potential trouble?). + * Consequently, threads should create and delete handlers + * themselves. I.e. a handler created by one should not be + * deleted by some other thread. + * *---------------------------------------------------------------------- */ @@ -268,26 +273,44 @@ Tcl_AsyncDelete( { ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); AsyncHandler *asyncPtr = (AsyncHandler *) async; - AsyncHandler *prevPtr; + AsyncHandler *prevPtr, *thisPtr; + + /* + * Assure early handling of the constraint + */ + + if (asyncPtr->originThrdId != Tcl_GetCurrentThread()) { + Tcl_Panic("Tcl_AsyncDelete: async handler deleted by the wrong thread"); + } + + /* + * If we come to this point when TSD's for the current + * thread have already been garbage-collected, we are + * in the _serious_ trouble. OTOH, we tolerate calling + * with already cleaned-up handler list (should we?). + */ Tcl_MutexLock(&tsdPtr->asyncMutex); - if (tsdPtr->firstHandler == asyncPtr) { - tsdPtr->firstHandler = asyncPtr->nextPtr; - if (tsdPtr->firstHandler == NULL) { - tsdPtr->lastHandler = NULL; + if (tsdPtr->firstHandler != NULL) { + prevPtr = thisPtr = tsdPtr->firstHandler; + while (thisPtr != NULL && thisPtr != asyncPtr) { + prevPtr = thisPtr; + thisPtr = thisPtr->nextPtr; } - } else { - prevPtr = tsdPtr->firstHandler; - while (prevPtr->nextPtr != asyncPtr) { - prevPtr = prevPtr->nextPtr; + if (thisPtr == NULL) { + Tcl_Panic("Tcl_AsyncDelete: cannot find async handler"); + } + if (asyncPtr == tsdPtr->firstHandler) { + tsdPtr->firstHandler = asyncPtr->nextPtr; + } else { + prevPtr->nextPtr = asyncPtr->nextPtr; } - prevPtr->nextPtr = asyncPtr->nextPtr; - if (tsdPtr->lastHandler == asyncPtr) { + if (asyncPtr == tsdPtr->lastHandler) { tsdPtr->lastHandler = prevPtr; } } Tcl_MutexUnlock(&tsdPtr->asyncMutex); - ckfree((char *) asyncPtr); + ckfree(asyncPtr); } /* @@ -315,6 +338,13 @@ Tcl_AsyncReady(void) ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); return tsdPtr->asyncReady; } + +int * +TclGetAsyncReadyPtr(void) +{ + ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); + return &(tsdPtr->asyncReady); +} /* * Local Variables: |