diff options
author | William Joye <wjoye@cfa.harvard.edu> | 2017-09-22 18:51:12 (GMT) |
---|---|---|
committer | William Joye <wjoye@cfa.harvard.edu> | 2017-09-22 18:51:12 (GMT) |
commit | 3fa8e6dc88e8041b6cb88d1b1e9c05676d3346b7 (patch) | |
tree | 69afbb41089c8358615879f7cd3c4cf7997f4c7e /tcl8.6/generic/tclAsync.c | |
parent | a0e17db23c0fd7c771c0afce8cce350c98f90b02 (diff) | |
download | blt-3fa8e6dc88e8041b6cb88d1b1e9c05676d3346b7.zip blt-3fa8e6dc88e8041b6cb88d1b1e9c05676d3346b7.tar.gz blt-3fa8e6dc88e8041b6cb88d1b1e9c05676d3346b7.tar.bz2 |
update to tcl/tk 8.6.7
Diffstat (limited to 'tcl8.6/generic/tclAsync.c')
-rw-r--r-- | tcl8.6/generic/tclAsync.c | 355 |
1 files changed, 0 insertions, 355 deletions
diff --git a/tcl8.6/generic/tclAsync.c b/tcl8.6/generic/tclAsync.c deleted file mode 100644 index 14804e4..0000000 --- a/tcl8.6/generic/tclAsync.c +++ /dev/null @@ -1,355 +0,0 @@ -/* - * tclAsync.c -- - * - * This file provides low-level support needed to invoke signal handlers - * in a safe way. The code here doesn't actually handle signals, though. - * This code is based on proposals made by Mark Diekhans and Don Libes. - * - * Copyright (c) 1993 The Regents of the University of California. - * Copyright (c) 1994 Sun Microsystems, Inc. - * - * See the file "license.terms" for information on usage and redistribution of - * this file, and for a DISCLAIMER OF ALL WARRANTIES. - */ - -#include "tclInt.h" - -/* Forward declaration */ -struct ThreadSpecificData; - -/* - * One of the following structures exists for each asynchronous handler: - */ - -typedef struct AsyncHandler { - int ready; /* Non-zero means this handler should be - * invoked in the next call to - * Tcl_AsyncInvoke. */ - struct AsyncHandler *nextPtr; - /* Next in list of all handlers for the - * process. */ - Tcl_AsyncProc *proc; /* Procedure to call when handler is - * invoked. */ - ClientData clientData; /* Value to pass to handler when it is - * invoked. */ - struct ThreadSpecificData *originTsd; - /* Used in Tcl_AsyncMark to modify thread- - * specific data from outside the thread it is - * associated to. */ - Tcl_ThreadId originThrdId; /* Origin thread where this token was created - * and where it will be yielded. */ -} AsyncHandler; - -typedef struct ThreadSpecificData { - /* - * The variables below maintain a list of all existing handlers specific - * to the calling thread. - */ - AsyncHandler *firstHandler; /* First handler defined for process, or NULL - * if none. */ - AsyncHandler *lastHandler; /* Last handler or NULL. */ - int asyncReady; /* This is set to 1 whenever a handler becomes - * ready and it is cleared to zero whenever - * Tcl_AsyncInvoke is called. It can be - * checked elsewhere in the application by - * calling Tcl_AsyncReady to see if - * Tcl_AsyncInvoke should be invoked. */ - int asyncActive; /* Indicates whether Tcl_AsyncInvoke is - * currently working. If so then we won't set - * asyncReady again until Tcl_AsyncInvoke - * returns. */ - Tcl_Mutex asyncMutex; /* Thread-specific AsyncHandler linked-list - * lock */ -} ThreadSpecificData; -static Tcl_ThreadDataKey dataKey; - -/* - *---------------------------------------------------------------------- - * - * TclFinalizeAsync -- - * - * Finalizes the mutex in the thread local data structure for the async - * subsystem. - * - * Results: - * None. - * - * Side effects: - * Forgets knowledge of the mutex should it have been created. - * - *---------------------------------------------------------------------- - */ - -void -TclFinalizeAsync(void) -{ - ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); - - if (tsdPtr->asyncMutex != NULL) { - Tcl_MutexFinalize(&tsdPtr->asyncMutex); - } -} - -/* - *---------------------------------------------------------------------- - * - * Tcl_AsyncCreate -- - * - * This procedure creates the data structures for an asynchronous - * handler, so that no memory has to be allocated when the handler is - * activated. - * - * Results: - * The return value is a token for the handler, which can be used to - * activate it later on. - * - * Side effects: - * Information about the handler is recorded. - * - *---------------------------------------------------------------------- - */ - -Tcl_AsyncHandler -Tcl_AsyncCreate( - Tcl_AsyncProc *proc, /* Procedure to call when handler is - * invoked. */ - ClientData clientData) /* Argument to pass to handler. */ -{ - AsyncHandler *asyncPtr; - ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); - - asyncPtr = ckalloc(sizeof(AsyncHandler)); - asyncPtr->ready = 0; - asyncPtr->nextPtr = NULL; - asyncPtr->proc = proc; - asyncPtr->clientData = clientData; - asyncPtr->originTsd = tsdPtr; - asyncPtr->originThrdId = Tcl_GetCurrentThread(); - - Tcl_MutexLock(&tsdPtr->asyncMutex); - if (tsdPtr->firstHandler == NULL) { - tsdPtr->firstHandler = asyncPtr; - } else { - tsdPtr->lastHandler->nextPtr = asyncPtr; - } - tsdPtr->lastHandler = asyncPtr; - Tcl_MutexUnlock(&tsdPtr->asyncMutex); - return (Tcl_AsyncHandler) asyncPtr; -} - -/* - *---------------------------------------------------------------------- - * - * Tcl_AsyncMark -- - * - * This procedure is called to request that an asynchronous handler be - * invoked as soon as possible. It's typically called from an interrupt - * handler, where it isn't safe to do anything that depends on or - * modifies application state. - * - * Results: - * None. - * - * Side effects: - * The handler gets marked for invocation later. - * - *---------------------------------------------------------------------- - */ - -void -Tcl_AsyncMark( - Tcl_AsyncHandler async) /* Token for handler. */ -{ - AsyncHandler *token = (AsyncHandler *) async; - - Tcl_MutexLock(&token->originTsd->asyncMutex); - token->ready = 1; - if (!token->originTsd->asyncActive) { - token->originTsd->asyncReady = 1; - Tcl_ThreadAlert(token->originThrdId); - } - Tcl_MutexUnlock(&token->originTsd->asyncMutex); -} - -/* - *---------------------------------------------------------------------- - * - * Tcl_AsyncInvoke -- - * - * This procedure is called at a "safe" time at background level to - * invoke any active asynchronous handlers. - * - * Results: - * The return value is a normal Tcl result, which is intended to replace - * the code argument as the current completion code for interp. - * - * Side effects: - * Depends on the handlers that are active. - * - *---------------------------------------------------------------------- - */ - -int -Tcl_AsyncInvoke( - Tcl_Interp *interp, /* If invoked from Tcl_Eval just after - * completing a command, points to - * interpreter. Otherwise it is NULL. */ - int code) /* If interp is non-NULL, this gives - * completion code from command that just - * completed. */ -{ - AsyncHandler *asyncPtr; - ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); - - Tcl_MutexLock(&tsdPtr->asyncMutex); - - if (tsdPtr->asyncReady == 0) { - Tcl_MutexUnlock(&tsdPtr->asyncMutex); - return code; - } - tsdPtr->asyncReady = 0; - tsdPtr->asyncActive = 1; - if (interp == NULL) { - code = 0; - } - - /* - * Make one or more passes over the list of handlers, invoking at most one - * handler in each pass. After invoking a handler, go back to the start of - * the list again so that (a) if a new higher-priority handler gets marked - * while executing a lower priority handler, we execute the higher- - * priority handler next, and (b) if a handler gets deleted during the - * execution of a handler, then the list structure may change so it isn't - * safe to continue down the list anyway. - */ - - while (1) { - for (asyncPtr = tsdPtr->firstHandler; asyncPtr != NULL; - asyncPtr = asyncPtr->nextPtr) { - if (asyncPtr->ready) { - break; - } - } - if (asyncPtr == NULL) { - break; - } - asyncPtr->ready = 0; - Tcl_MutexUnlock(&tsdPtr->asyncMutex); - code = asyncPtr->proc(asyncPtr->clientData, interp, code); - Tcl_MutexLock(&tsdPtr->asyncMutex); - } - tsdPtr->asyncActive = 0; - Tcl_MutexUnlock(&tsdPtr->asyncMutex); - return code; -} - -/* - *---------------------------------------------------------------------- - * - * Tcl_AsyncDelete -- - * - * Frees up all the state for an asynchronous handler. The handler should - * never be used again. - * - * Results: - * None. - * - * 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. - * - *---------------------------------------------------------------------- - */ - -void -Tcl_AsyncDelete( - Tcl_AsyncHandler async) /* Token for handler to delete. */ -{ - ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); - AsyncHandler *asyncPtr = (AsyncHandler *) async; - 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 != NULL) { - prevPtr = thisPtr = tsdPtr->firstHandler; - while (thisPtr != NULL && thisPtr != asyncPtr) { - prevPtr = thisPtr; - thisPtr = thisPtr->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; - } - if (asyncPtr == tsdPtr->lastHandler) { - tsdPtr->lastHandler = prevPtr; - } - } - Tcl_MutexUnlock(&tsdPtr->asyncMutex); - ckfree(asyncPtr); -} - -/* - *---------------------------------------------------------------------- - * - * Tcl_AsyncReady -- - * - * This procedure can be used to tell whether Tcl_AsyncInvoke needs to be - * called. This procedure is the external interface for checking the - * thread-specific asyncReady variable. - * - * Results: - * The return value is 1 whenever a handler is ready and is 0 when no - * handlers are ready. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------- - */ - -int -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: - * mode: c - * c-basic-offset: 4 - * fill-column: 78 - * End: - */ |