diff options
Diffstat (limited to 'generic/tclAsync.c')
-rw-r--r-- | generic/tclAsync.c | 207 |
1 files changed, 103 insertions, 104 deletions
diff --git a/generic/tclAsync.c b/generic/tclAsync.c index 98087c5..f210004 100644 --- a/generic/tclAsync.c +++ b/generic/tclAsync.c @@ -1,91 +1,78 @@ -/* +/* * 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. + * 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. + * See the file "license.terms" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tclInt.h" -#include "tclPort.h" /* Forward declaration */ struct ThreadSpecificData; /* - * One of the following structures exists for each asynchronous - * handler: + * 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. */ + 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. */ + /* 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. */ - - /* - * 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. + * The variables below maintain a list of all existing handlers specific + * to the calling thread. */ - - int asyncReady; - - /* - * The variable below indicates whether Tcl_AsyncInvoke is currently - * working. If so then we won't set asyncReady again until - * Tcl_AsyncInvoke returns. - */ - - int asyncActive; - - Tcl_Mutex asyncMutex; /* Thread-specific AsyncHandler linked-list lock */ - + 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. + * Finalizes the mutex in the thread local data structure for the async + * subsystem. * * Results: - * None. + * None. * * Side effects: * Forgets knowledge of the mutex should it have been created. @@ -94,7 +81,7 @@ static Tcl_ThreadDataKey dataKey; */ void -TclFinalizeAsync() +TclFinalizeAsync(void) { ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); @@ -109,12 +96,12 @@ TclFinalizeAsync() * 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. + * 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. + * 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. @@ -123,10 +110,10 @@ TclFinalizeAsync() */ Tcl_AsyncHandler -Tcl_AsyncCreate(proc, clientData) - Tcl_AsyncProc *proc; /* Procedure to call when handler - * is invoked. */ - ClientData clientData; /* Argument to pass to handler. */ +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); @@ -155,10 +142,10 @@ Tcl_AsyncCreate(proc, clientData) * * 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. + * 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. @@ -170,8 +157,8 @@ Tcl_AsyncCreate(proc, clientData) */ void -Tcl_AsyncMark(async) - Tcl_AsyncHandler async; /* Token for handler. */ +Tcl_AsyncMark( + Tcl_AsyncHandler async) /* Token for handler. */ { AsyncHandler *token = (AsyncHandler *) async; @@ -189,13 +176,12 @@ Tcl_AsyncMark(async) * * Tcl_AsyncInvoke -- * - * This procedure is called at a "safe" time at background level - * to invoke any active asynchronous handlers. + * 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. + * 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. @@ -204,14 +190,13 @@ Tcl_AsyncMark(async) */ 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. */ +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); @@ -229,13 +214,12 @@ Tcl_AsyncInvoke(interp, code) } /* - * 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 + * 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. */ @@ -251,7 +235,7 @@ Tcl_AsyncInvoke(interp, code) } 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; @@ -264,8 +248,8 @@ Tcl_AsyncInvoke(interp, code) * * Tcl_AsyncDelete -- * - * Frees up all the state for an asynchronous handler. The handler - * should never be used again. + * Frees up all the state for an asynchronous handler. The handler should + * never be used again. * * Results: * None. @@ -276,7 +260,7 @@ Tcl_AsyncInvoke(interp, code) * 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 + * Consequently, threads should create and delete handlers * themselves. I.e. a handler created by one should not be * deleted by some other thread. * @@ -284,8 +268,8 @@ Tcl_AsyncInvoke(interp, code) */ void -Tcl_AsyncDelete(async) - Tcl_AsyncHandler async; /* Token for handler to delete. */ +Tcl_AsyncDelete( + Tcl_AsyncHandler async) /* Token for handler to delete. */ { ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); AsyncHandler *asyncPtr = (AsyncHandler *) async; @@ -296,7 +280,7 @@ Tcl_AsyncDelete(async) */ if (asyncPtr->originThrdId != Tcl_GetCurrentThread()) { - panic("Tcl_AsyncDelete: async handler deleted by the wrong thread"); + Tcl_Panic("Tcl_AsyncDelete: async handler deleted by the wrong thread"); } /* @@ -314,7 +298,7 @@ Tcl_AsyncDelete(async) thisPtr = thisPtr->nextPtr; } if (thisPtr == NULL) { - panic("Tcl_AsyncDelete: cannot find async handler"); + Tcl_Panic("Tcl_AsyncDelete: cannot find async handler"); } if (asyncPtr == tsdPtr->firstHandler) { tsdPtr->firstHandler = asyncPtr->nextPtr; @@ -334,13 +318,13 @@ Tcl_AsyncDelete(async) * * 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. + * 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. + * The return value is 1 whenever a handler is ready and is 0 when no + * handlers are ready. * * Side effects: * None. @@ -349,8 +333,23 @@ Tcl_AsyncDelete(async) */ int -Tcl_AsyncReady() +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: + */ |