⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tclnotify.c

📁 tcl是工具命令语言
💻 C
📖 第 1 页 / 共 3 页
字号:
    Tcl_ThreadId threadId;	/* Identifier for thread to use. */    Tcl_Event* evPtr;		/* Event to add to queue.  The storage				 * space must have been allocated the caller				 * with malloc (ckalloc), and it becomes				 * the property of the event queue.  It				 * will be freed after the event has been				 * handled. */    Tcl_QueuePosition position;	/* One of TCL_QUEUE_TAIL, TCL_QUEUE_HEAD,				 * TCL_QUEUE_MARK. */{    ThreadSpecificData *tsdPtr;    /*     * Find the notifier associated with the specified thread.     */    Tcl_MutexLock(&listLock);    for (tsdPtr = firstNotifierPtr; tsdPtr && tsdPtr->threadId != threadId;	     tsdPtr = tsdPtr->nextPtr) {	/* Empty loop body. */    }    /*     * Queue the event if there was a notifier associated with the thread.     */    if (tsdPtr) {	QueueEvent(tsdPtr, evPtr, position);    }    Tcl_MutexUnlock(&listLock);}/* *---------------------------------------------------------------------- * * QueueEvent -- * *	Insert an event into the specified thread's event queue at one *	of three positions: the head, the tail, or before a floating *	marker. Events inserted before the marker will be processed in *	first-in-first-out order, but before any events inserted at *	the tail of the queue.  Events inserted at the head of the *	queue will be processed in last-in-first-out order. * * Results: *	None. * * Side effects: *	None. * *---------------------------------------------------------------------- */static voidQueueEvent(tsdPtr, evPtr, position)    ThreadSpecificData *tsdPtr;	/* Handle to thread local data that indicates				 * which event queue to use. */    Tcl_Event* evPtr;		/* Event to add to queue.  The storage				 * space must have been allocated the caller				 * with malloc (ckalloc), and it becomes				 * the property of the event queue.  It				 * will be freed after the event has been				 * handled. */    Tcl_QueuePosition position;	/* One of TCL_QUEUE_TAIL, TCL_QUEUE_HEAD,				 * TCL_QUEUE_MARK. */{    Tcl_MutexLock(&(tsdPtr->queueMutex));    if (position == TCL_QUEUE_TAIL) {	/*	 * Append the event on the end of the queue.	 */	evPtr->nextPtr = NULL;	if (tsdPtr->firstEventPtr == NULL) {	    tsdPtr->firstEventPtr = evPtr;	} else {	    tsdPtr->lastEventPtr->nextPtr = evPtr;	}	tsdPtr->lastEventPtr = evPtr;    } else if (position == TCL_QUEUE_HEAD) {	/*	 * Push the event on the head of the queue.	 */	evPtr->nextPtr = tsdPtr->firstEventPtr;	if (tsdPtr->firstEventPtr == NULL) {	    tsdPtr->lastEventPtr = evPtr;	}	    	tsdPtr->firstEventPtr = evPtr;    } else if (position == TCL_QUEUE_MARK) {	/*	 * Insert the event after the current marker event and advance	 * the marker to the new event.	 */	if (tsdPtr->markerEventPtr == NULL) {	    evPtr->nextPtr = tsdPtr->firstEventPtr;	    tsdPtr->firstEventPtr = evPtr;	} else {	    evPtr->nextPtr = tsdPtr->markerEventPtr->nextPtr;	    tsdPtr->markerEventPtr->nextPtr = evPtr;	}	tsdPtr->markerEventPtr = evPtr;	if (evPtr->nextPtr == NULL) {	    tsdPtr->lastEventPtr = evPtr;	}    }    Tcl_MutexUnlock(&(tsdPtr->queueMutex));}/* *---------------------------------------------------------------------- * * Tcl_DeleteEvents -- * *	Calls a procedure for each event in the queue and deletes those *	for which the procedure returns 1. Events for which the *	procedure returns 0 are left in the queue.  Operates on the *	queue associated with the current thread. * * Results: *	None. * * Side effects: *	Potentially removes one or more events from the event queue. * *---------------------------------------------------------------------- */voidTcl_DeleteEvents(proc, clientData)    Tcl_EventDeleteProc *proc;		/* The procedure to call. */    ClientData clientData;    		/* type-specific data. */{    Tcl_Event *evPtr, *prevPtr, *hold;    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);    Tcl_MutexLock(&(tsdPtr->queueMutex));    for (prevPtr = (Tcl_Event *) NULL, evPtr = tsdPtr->firstEventPtr;             evPtr != (Tcl_Event *) NULL;             ) {        if ((*proc) (evPtr, clientData) == 1) {            if (tsdPtr->firstEventPtr == evPtr) {                tsdPtr->firstEventPtr = evPtr->nextPtr;            } else {                prevPtr->nextPtr = evPtr->nextPtr;            }            if (evPtr->nextPtr == (Tcl_Event *) NULL) {                tsdPtr->lastEventPtr = prevPtr;            }            if (tsdPtr->markerEventPtr == evPtr) {                tsdPtr->markerEventPtr = prevPtr;            }            hold = evPtr;            evPtr = evPtr->nextPtr;            ckfree((char *) hold);        } else {            prevPtr = evPtr;            evPtr = evPtr->nextPtr;        }    }    Tcl_MutexUnlock(&(tsdPtr->queueMutex));}/* *---------------------------------------------------------------------- * * Tcl_ServiceEvent -- * *	Process one event from the event queue, or invoke an *	asynchronous event handler.  Operates on event queue for *	current thread. * * Results: *	The return value is 1 if the procedure actually found an event *	to process.  If no processing occurred, then 0 is returned. * * Side effects: *	Invokes all of the event handlers for the highest priority *	event in the event queue.  May collapse some events into a *	single event or discard stale events. * *---------------------------------------------------------------------- */intTcl_ServiceEvent(flags)    int flags;			/* Indicates what events should be processed.				 * May be any combination of TCL_WINDOW_EVENTS				 * TCL_FILE_EVENTS, TCL_TIMER_EVENTS, or other				 * flags defined elsewhere.  Events not				 * matching this will be skipped for processing				 * later. */{    Tcl_Event *evPtr, *prevPtr;    Tcl_EventProc *proc;    int result;    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);    /*     * Asynchronous event handlers are considered to be the highest     * priority events, and so must be invoked before we process events     * on the event queue.     */        if (Tcl_AsyncReady()) {	(void) Tcl_AsyncInvoke((Tcl_Interp *) NULL, 0);	return 1;    }    /*     * No event flags is equivalent to TCL_ALL_EVENTS.     */        if ((flags & TCL_ALL_EVENTS) == 0) {	flags |= TCL_ALL_EVENTS;    }    /*     * Loop through all the events in the queue until we find one     * that can actually be handled.     */    Tcl_MutexLock(&(tsdPtr->queueMutex));    for (evPtr = tsdPtr->firstEventPtr; evPtr != NULL;	 evPtr = evPtr->nextPtr) {	/*	 * Call the handler for the event.  If it actually handles the	 * event then free the storage for the event.  There are two	 * tricky things here, both stemming from the fact that the event	 * code may be re-entered while servicing the event:	 *	 * 1. Set the "proc" field to NULL.  This is a signal to ourselves	 *    that we shouldn't reexecute the handler if the event loop	 *    is re-entered.	 * 2. When freeing the event, must search the queue again from the	 *    front to find it.  This is because the event queue could	 *    change almost arbitrarily while handling the event, so we	 *    can't depend on pointers found now still being valid when	 *    the handler returns.	 */	proc = evPtr->proc;	if (proc == NULL) {	    continue;	}	evPtr->proc = NULL;	/*	 * Release the lock before calling the event procedure.  This	 * allows other threads to post events if we enter a recursive	 * event loop in this thread.  Note that we are making the assumption	 * that if the proc returns 0, the event is still in the list.	 */	Tcl_MutexUnlock(&(tsdPtr->queueMutex));	result = (*proc)(evPtr, flags);	Tcl_MutexLock(&(tsdPtr->queueMutex));	if (result) {	    /*	     * The event was processed, so remove it from the queue.	     */	    if (tsdPtr->firstEventPtr == evPtr) {		tsdPtr->firstEventPtr = evPtr->nextPtr;		if (evPtr->nextPtr == NULL) {		    tsdPtr->lastEventPtr = NULL;		}		if (tsdPtr->markerEventPtr == evPtr) {		    tsdPtr->markerEventPtr = NULL;		}	    } else {		for (prevPtr = tsdPtr->firstEventPtr;		     prevPtr && prevPtr->nextPtr != evPtr;		     prevPtr = prevPtr->nextPtr) {		    /* Empty loop body. */		}		if (prevPtr) {		    prevPtr->nextPtr = evPtr->nextPtr;		    if (evPtr->nextPtr == NULL) {			tsdPtr->lastEventPtr = prevPtr;		    }		    if (tsdPtr->markerEventPtr == evPtr) {			tsdPtr->markerEventPtr = prevPtr;		    }		} else {		    evPtr = NULL;		}	    }	    if (evPtr) {		ckfree((char *) evPtr);	    }	    Tcl_MutexUnlock(&(tsdPtr->queueMutex));	    return 1;	} else {	    /*	     * The event wasn't actually handled, so we have to restore	     * the proc field to allow the event to be attempted again.	     */	    evPtr->proc = proc;	}    }    Tcl_MutexUnlock(&(tsdPtr->queueMutex));    return 0;}/* *---------------------------------------------------------------------- * * Tcl_GetServiceMode -- * *	This routine returns the current service mode of the notifier. * * Results: *	Returns either TCL_SERVICE_ALL or TCL_SERVICE_NONE. * * Side effects: *	None. * *---------------------------------------------------------------------- */intTcl_GetServiceMode(){    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);    return tsdPtr->serviceMode;}/* *---------------------------------------------------------------------- * * Tcl_SetServiceMode -- * *	This routine sets the current service mode of the tsdPtr-> * * Results: *	Returns the previous service mode. * * Side effects: *	Invokes the notifier service mode hook procedure. * *---------------------------------------------------------------------- */intTcl_SetServiceMode(mode)    int mode;			/* New service mode: TCL_SERVICE_ALL or				 * TCL_SERVICE_NONE */{    int oldMode;    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);    oldMode = tsdPtr->serviceMode;    tsdPtr->serviceMode = mode;    if (tclStubs.tcl_ServiceModeHook) {	tclStubs.tcl_ServiceModeHook(mode);    }    return oldMode;}/* *---------------------------------------------------------------------- * * Tcl_SetMaxBlockTime --

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -