diff options
Diffstat (limited to 'generic/tclAsync.c')
-rw-r--r-- | generic/tclAsync.c | 280 |
1 files changed, 0 insertions, 280 deletions
diff --git a/generic/tclAsync.c b/generic/tclAsync.c deleted file mode 100644 index fc80385..0000000 --- a/generic/tclAsync.c +++ /dev/null @@ -1,280 +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. - * - * RCS: @(#) $Id: tclAsync.c,v 1.4 1999/04/16 00:46:42 stanton Exp $ - */ - -#include "tclInt.h" -#include "tclPort.h" - -/* - * 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. */ -} AsyncHandler; - -/* - * The variables below maintain a list of all existing handlers. - */ - -static AsyncHandler *firstHandler; /* First handler defined for process, - * or NULL if none. */ -static AsyncHandler *lastHandler; /* Last handler or NULL. */ - -TCL_DECLARE_MUTEX(asyncMutex) /* Process-wide async handler lock */ - -/* - * The variable below 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. - */ - -static int asyncReady = 0; - -/* - * The variable below indicates whether Tcl_AsyncInvoke is currently - * working. If so then we won't set asyncReady again until - * Tcl_AsyncInvoke returns. - */ - -static int asyncActive = 0; - -/* - *---------------------------------------------------------------------- - * - * 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(proc, clientData) - Tcl_AsyncProc *proc; /* Procedure to call when handler - * is invoked. */ - ClientData clientData; /* Argument to pass to handler. */ -{ - AsyncHandler *asyncPtr; - - asyncPtr = (AsyncHandler *) ckalloc(sizeof(AsyncHandler)); - asyncPtr->ready = 0; - asyncPtr->nextPtr = NULL; - asyncPtr->proc = proc; - asyncPtr->clientData = clientData; - Tcl_MutexLock(&asyncMutex); - if (firstHandler == NULL) { - firstHandler = asyncPtr; - } else { - lastHandler->nextPtr = asyncPtr; - } - lastHandler = asyncPtr; - Tcl_MutexUnlock(&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(async) - Tcl_AsyncHandler async; /* Token for handler. */ -{ - Tcl_MutexLock(&asyncMutex); - ((AsyncHandler *) async)->ready = 1; - if (!asyncActive) { - asyncReady = 1; - TclpAsyncMark(async); - } - Tcl_MutexUnlock(&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(interp, code) - 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; - Tcl_MutexLock(&asyncMutex); - - if (asyncReady == 0) { - Tcl_MutexUnlock(&asyncMutex); - return code; - } - asyncReady = 0; - 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 = firstHandler; asyncPtr != NULL; - asyncPtr = asyncPtr->nextPtr) { - if (asyncPtr->ready) { - break; - } - } - if (asyncPtr == NULL) { - break; - } - asyncPtr->ready = 0; - Tcl_MutexUnlock(&asyncMutex); - code = (*asyncPtr->proc)(asyncPtr->clientData, interp, code); - Tcl_MutexLock(&asyncMutex); - } - asyncActive = 0; - Tcl_MutexUnlock(&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. - * - *---------------------------------------------------------------------- - */ - -void -Tcl_AsyncDelete(async) - Tcl_AsyncHandler async; /* Token for handler to delete. */ -{ - AsyncHandler *asyncPtr = (AsyncHandler *) async; - AsyncHandler *prevPtr; - - Tcl_MutexLock(&asyncMutex); - if (firstHandler == asyncPtr) { - firstHandler = asyncPtr->nextPtr; - if (firstHandler == NULL) { - lastHandler = NULL; - } - } else { - prevPtr = firstHandler; - while (prevPtr->nextPtr != asyncPtr) { - prevPtr = prevPtr->nextPtr; - } - prevPtr->nextPtr = asyncPtr->nextPtr; - if (lastHandler == asyncPtr) { - lastHandler = prevPtr; - } - } - Tcl_MutexUnlock(&asyncMutex); - ckfree((char *) 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 internal 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() -{ - return asyncReady; -} |