source: HiSusy/trunk/Delphes/Delphes-3.0.9/external/tcl/tclAsync.c @ 5

Last change on this file since 5 was 5, checked in by zerwas, 11 years ago

update to Delphes-3.0.9

File size: 6.8 KB
Line 
1/*
2 * tclAsync.c --
3 *
4 *      This file provides low-level support needed to invoke signal
5 *      handlers in a safe way.  The code here doesn't actually handle
6 *      signals, though.  This code is based on proposals made by
7 *      Mark Diekhans and Don Libes.
8 *
9 * Copyright (c) 1993 The Regents of the University of California.
10 * Copyright (c) 1994 Sun Microsystems, Inc.
11 *
12 * See the file "license.terms" for information on usage and redistribution
13 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
14 *
15 * RCS: @(#) $Id: tclAsync.c,v 1.1 2008-06-04 13:58:03 demin Exp $
16 */
17
18#include "tclInt.h"
19
20/*
21 * One of the following structures exists for each asynchronous
22 * handler:
23 */
24
25typedef struct AsyncHandler {
26    int ready;                          /* Non-zero means this handler should
27                                         * be invoked in the next call to
28                                         * Tcl_AsyncInvoke. */
29    struct AsyncHandler *nextPtr;       /* Next in list of all handlers for
30                                         * the process. */
31    Tcl_AsyncProc *proc;                /* Procedure to call when handler
32                                         * is invoked. */
33    ClientData clientData;              /* Value to pass to handler when it
34                                         * is invoked. */
35} AsyncHandler;
36
37/*
38 * The variables below maintain a list of all existing handlers.
39 */
40
41static AsyncHandler *firstHandler;      /* First handler defined for process,
42                                         * or NULL if none. */
43static AsyncHandler *lastHandler;       /* Last handler or NULL. */
44
45/*
46 * The variable below is set to 1 whenever a handler becomes ready and
47 * it is cleared to zero whenever Tcl_AsyncInvoke is called.  It can be
48 * checked elsewhere in the application by calling Tcl_AsyncReady to see
49 * if Tcl_AsyncInvoke should be invoked.
50 */
51
52static int asyncReady = 0;
53
54/*
55 * The variable below indicates whether Tcl_AsyncInvoke is currently
56 * working.  If so then we won't set asyncReady again until
57 * Tcl_AsyncInvoke returns.
58 */
59
60static int asyncActive = 0;
61
62/*
63 *----------------------------------------------------------------------
64 *
65 * Tcl_AsyncCreate --
66 *
67 *      This procedure creates the data structures for an asynchronous
68 *      handler, so that no memory has to be allocated when the handler
69 *      is activated.
70 *
71 * Results:
72 *      The return value is a token for the handler, which can be used
73 *      to activate it later on.
74 *
75 * Side effects:
76 *      Information about the handler is recorded.
77 *
78 *----------------------------------------------------------------------
79 */
80
81Tcl_AsyncHandler
82Tcl_AsyncCreate(proc, clientData)
83    Tcl_AsyncProc *proc;                /* Procedure to call when handler
84                                         * is invoked. */
85    ClientData clientData;              /* Argument to pass to handler. */
86{
87    AsyncHandler *asyncPtr;
88
89    asyncPtr = (AsyncHandler *) ckalloc(sizeof(AsyncHandler));
90    asyncPtr->ready = 0;
91    asyncPtr->nextPtr = NULL;
92    asyncPtr->proc = proc;
93    asyncPtr->clientData = clientData;
94    if (firstHandler == NULL) {
95        firstHandler = asyncPtr;
96    } else {
97        lastHandler->nextPtr = asyncPtr;
98    }
99    lastHandler = asyncPtr;
100    return (Tcl_AsyncHandler) asyncPtr;
101}
102
103/*
104 *----------------------------------------------------------------------
105 *
106 * Tcl_AsyncMark --
107 *
108 *      This procedure is called to request that an asynchronous handler
109 *      be invoked as soon as possible.  It's typically called from
110 *      an interrupt handler, where it isn't safe to do anything that
111 *      depends on or modifies application state.
112 *
113 * Results:
114 *      None.
115 *
116 * Side effects:
117 *      The handler gets marked for invocation later.
118 *
119 *----------------------------------------------------------------------
120 */
121
122void
123Tcl_AsyncMark(async)
124    Tcl_AsyncHandler async;             /* Token for handler. */
125{
126    ((AsyncHandler *) async)->ready = 1;
127    if (!asyncActive) {
128        asyncReady = 1;
129    }
130}
131
132/*
133 *----------------------------------------------------------------------
134 *
135 * Tcl_AsyncInvoke --
136 *
137 *      This procedure is called at a "safe" time at background level
138 *      to invoke any active asynchronous handlers.
139 *
140 * Results:
141 *      The return value is a normal Tcl result, which is intended to
142 *      replace the code argument as the current completion code for
143 *      interp.
144 *
145 * Side effects:
146 *      Depends on the handlers that are active.
147 *
148 *----------------------------------------------------------------------
149 */
150
151int
152Tcl_AsyncInvoke(interp, code)
153    Tcl_Interp *interp;                 /* If invoked from Tcl_Eval just after
154                                         * completing a command, points to
155                                         * interpreter.  Otherwise it is
156                                         * NULL. */
157    int code;                           /* If interp is non-NULL, this gives
158                                         * completion code from command that
159                                         * just completed. */
160{
161    AsyncHandler *asyncPtr;
162
163    if (asyncReady == 0) {
164        return code;
165    }
166    asyncReady = 0;
167    asyncActive = 1;
168    if (interp == NULL) {
169        code = 0;
170    }
171
172    /*
173     * Make one or more passes over the list of handlers, invoking
174     * at most one handler in each pass.  After invoking a handler,
175     * go back to the start of the list again so that (a) if a new
176     * higher-priority handler gets marked while executing a lower
177     * priority handler, we execute the higher-priority handler
178     * next, and (b) if a handler gets deleted during the execution
179     * of a handler, then the list structure may change so it isn't
180     * safe to continue down the list anyway.
181     */
182
183    while (1) {
184        for (asyncPtr = firstHandler; asyncPtr != NULL;
185                asyncPtr = asyncPtr->nextPtr) {
186            if (asyncPtr->ready) {
187                break;
188            }
189        }
190        if (asyncPtr == NULL) {
191            break;
192        }
193        asyncPtr->ready = 0;
194        code = (*asyncPtr->proc)(asyncPtr->clientData, interp, code);
195    }
196    asyncActive = 0;
197    return code;
198}
199
200/*
201 *----------------------------------------------------------------------
202 *
203 * Tcl_AsyncDelete --
204 *
205 *      Frees up all the state for an asynchronous handler.  The handler
206 *      should never be used again.
207 *
208 * Results:
209 *      None.
210 *
211 * Side effects:
212 *      The state associated with the handler is deleted.
213 *
214 *----------------------------------------------------------------------
215 */
216
217void
218Tcl_AsyncDelete(async)
219    Tcl_AsyncHandler async;             /* Token for handler to delete. */
220{
221    AsyncHandler *asyncPtr = (AsyncHandler *) async;
222    AsyncHandler *prevPtr;
223
224    if (firstHandler == asyncPtr) {
225        firstHandler = asyncPtr->nextPtr;
226        if (firstHandler == NULL) {
227            lastHandler = NULL;
228        }
229    } else {
230        prevPtr = firstHandler;
231        while (prevPtr->nextPtr != asyncPtr) {
232            prevPtr = prevPtr->nextPtr;
233        }
234        prevPtr->nextPtr = asyncPtr->nextPtr;
235        if (lastHandler == asyncPtr) {
236            lastHandler = prevPtr;
237        }
238    }
239    ckfree((char *) asyncPtr);
240}
241
242/*
243 *----------------------------------------------------------------------
244 *
245 * Tcl_AsyncReady --
246 *
247 *      This procedure can be used to tell whether Tcl_AsyncInvoke
248 *      needs to be called.  This procedure is the external interface
249 *      for checking the internal asyncReady variable.
250 *
251 * Results:
252 *      The return value is 1 whenever a handler is ready and is 0
253 *      when no handlers are ready.
254 *
255 * Side effects:
256 *      None.
257 *
258 *----------------------------------------------------------------------
259 */
260
261int
262Tcl_AsyncReady()
263{
264    return asyncReady;
265}
Note: See TracBrowser for help on using the repository browser.