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: | 
