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

📄 tclnotify.c

📁 tcl是工具命令语言
💻 C
📖 第 1 页 / 共 3 页
字号:
 * *	This procedure is invoked by event sources to tell the notifier *	how long it may block the next time it blocks.  The timePtr *	argument gives a maximum time;  the actual time may be less if *	some other event source requested a smaller time. * * Results: *	None. * * Side effects: *	May reduce the length of the next sleep in the tsdPtr-> * *---------------------------------------------------------------------- */voidTcl_SetMaxBlockTime(timePtr)    Tcl_Time *timePtr;		/* Specifies a maximum elapsed time for				 * the next blocking operation in the				 * event tsdPtr-> */{    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);    if (!tsdPtr->blockTimeSet || (timePtr->sec < tsdPtr->blockTime.sec)	    || ((timePtr->sec == tsdPtr->blockTime.sec)	    && (timePtr->usec < tsdPtr->blockTime.usec))) {	tsdPtr->blockTime = *timePtr;	tsdPtr->blockTimeSet = 1;    }    /*     * If we are called outside an event source traversal, set the     * timeout immediately.     */    if (!tsdPtr->inTraversal) {	if (tsdPtr->blockTimeSet) {	    Tcl_SetTimer(&tsdPtr->blockTime);	} else {	    Tcl_SetTimer(NULL);	}    }}/* *---------------------------------------------------------------------- * * Tcl_DoOneEvent -- * *	Process a single event of some sort.  If there's no work to *	do, wait for an event to occur, then process it. * * Results: *	The return value is 1 if the procedure actually found an event *	to process.  If no processing occurred, then 0 is returned (this *	can happen if the TCL_DONT_WAIT flag is set or if there are no *	event handlers to wait for in the set specified by flags). * * Side effects: *	May delay execution of process while waiting for an event, *	unless TCL_DONT_WAIT is set in the flags argument.  Event *	sources are invoked to check for and queue events.  Event *	handlers may produce arbitrary side effects. * *---------------------------------------------------------------------- */intTcl_DoOneEvent(flags)    int flags;			/* Miscellaneous flag values:  may be any				 * combination of TCL_DONT_WAIT,				 * TCL_WINDOW_EVENTS, TCL_FILE_EVENTS,				 * TCL_TIMER_EVENTS, TCL_IDLE_EVENTS, or				 * others defined by event sources. */{    int result = 0, oldMode;    EventSource *sourcePtr;    Tcl_Time *timePtr;    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);    /*     * The first thing we do is to service any asynchronous event     * handlers.     */        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;    }    /*     * Set the service mode to none so notifier event routines won't     * try to service events recursively.     */    oldMode = tsdPtr->serviceMode;    tsdPtr->serviceMode = TCL_SERVICE_NONE;    /*     * The core of this procedure is an infinite loop, even though     * we only service one event.  The reason for this is that we     * may be processing events that don't do anything inside of Tcl.     */    while (1) {	/*	 * If idle events are the only things to service, skip the	 * main part of the loop and go directly to handle idle	 * events (i.e. don't wait even if TCL_DONT_WAIT isn't set).	 */	if ((flags & TCL_ALL_EVENTS) == TCL_IDLE_EVENTS) {	    flags = TCL_IDLE_EVENTS|TCL_DONT_WAIT;	    goto idleEvents;	}	/*	 * Ask Tcl to service a queued event, if there are any.	 */	if (Tcl_ServiceEvent(flags)) {	    result = 1;	    	    break;	}	/*	 * If TCL_DONT_WAIT is set, be sure to poll rather than	 * blocking, otherwise reset the block time to infinity.	 */	if (flags & TCL_DONT_WAIT) {	    tsdPtr->blockTime.sec = 0;	    tsdPtr->blockTime.usec = 0;	    tsdPtr->blockTimeSet = 1;	} else {	    tsdPtr->blockTimeSet = 0;	}	/*	 * Set up all the event sources for new events.  This will	 * cause the block time to be updated if necessary.	 */	tsdPtr->inTraversal = 1;	for (sourcePtr = tsdPtr->firstEventSourcePtr; sourcePtr != NULL;	     sourcePtr = sourcePtr->nextPtr) {	    if (sourcePtr->setupProc) {		(sourcePtr->setupProc)(sourcePtr->clientData, flags);	    }	}	tsdPtr->inTraversal = 0;	if ((flags & TCL_DONT_WAIT) || tsdPtr->blockTimeSet) {	    timePtr = &tsdPtr->blockTime;	} else {	    timePtr = NULL;	}	/*	 * Wait for a new event or a timeout.  If Tcl_WaitForEvent	 * returns -1, we should abort Tcl_DoOneEvent.	 */	result = Tcl_WaitForEvent(timePtr);	if (result < 0) {	    result = 0;	    break;	}	/*	 * Check all the event sources for new events.	 */	for (sourcePtr = tsdPtr->firstEventSourcePtr; sourcePtr != NULL;	     sourcePtr = sourcePtr->nextPtr) {	    if (sourcePtr->checkProc) {		(sourcePtr->checkProc)(sourcePtr->clientData, flags);	    }	}	/*	 * Check for events queued by the notifier or event sources.	 */	if (Tcl_ServiceEvent(flags)) {	    result = 1;	    break;	}	/*	 * We've tried everything at this point, but nobody we know	 * about had anything to do.  Check for idle events.  If none,	 * either quit or go back to the top and try again.	 */	idleEvents:	if (flags & TCL_IDLE_EVENTS) {	    if (TclServiceIdle()) {		result = 1;		break;	    }	}	if (flags & TCL_DONT_WAIT) {	    break;	}	/*	 * If Tcl_WaitForEvent has returned 1,	 * indicating that one system event has been dispatched	 * (and thus that some Tcl code might have been indirectly executed),	 * we break out of the loop.	 * We do this to give VwaitCmd for instance a chance to check 	 * if that system event had the side effect of changing the 	 * variable (so the vwait can return and unwind properly).	 *	 * NB: We will process idle events if any first, because	 *     otherwise we might never do the idle events if the notifier	 *     always gets system events.	 */	if (result) {	    break;	}    }    tsdPtr->serviceMode = oldMode;    return result;}/* *---------------------------------------------------------------------- * * Tcl_ServiceAll -- * *	This routine checks all of the event sources, processes *	events that are on the Tcl event queue, and then calls the *	any idle handlers.  Platform specific notifier callbacks that *	generate events should call this routine before returning to *	the system in order to ensure that Tcl gets a chance to *	process the new events. * * Results: *	Returns 1 if an event or idle handler was invoked, else 0. * * Side effects: *	Anything that an event or idle handler may do. * *---------------------------------------------------------------------- */intTcl_ServiceAll(){    int result = 0;    EventSource *sourcePtr;    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);    if (tsdPtr->serviceMode == TCL_SERVICE_NONE) {	return result;    }    /*     * We need to turn off event servicing like we to in Tcl_DoOneEvent,     * to avoid recursive calls.     */        tsdPtr->serviceMode = TCL_SERVICE_NONE;    /*     * Check async handlers first.     */    if (Tcl_AsyncReady()) {	(void) Tcl_AsyncInvoke((Tcl_Interp *) NULL, 0);    }    /*     * Make a single pass through all event sources, queued events,     * and idle handlers.  Note that we wait to update the notifier     * timer until the end so we can avoid multiple changes.     */    tsdPtr->inTraversal = 1;    tsdPtr->blockTimeSet = 0;    for (sourcePtr = tsdPtr->firstEventSourcePtr; sourcePtr != NULL;	 sourcePtr = sourcePtr->nextPtr) {	if (sourcePtr->setupProc) {	    (sourcePtr->setupProc)(sourcePtr->clientData, TCL_ALL_EVENTS);	}    }    for (sourcePtr = tsdPtr->firstEventSourcePtr; sourcePtr != NULL;	 sourcePtr = sourcePtr->nextPtr) {	if (sourcePtr->checkProc) {	    (sourcePtr->checkProc)(sourcePtr->clientData, TCL_ALL_EVENTS);	}    }    while (Tcl_ServiceEvent(0)) {	result = 1;    }    if (TclServiceIdle()) {	result = 1;    }    if (!tsdPtr->blockTimeSet) {	Tcl_SetTimer(NULL);    } else {	Tcl_SetTimer(&tsdPtr->blockTime);    }    tsdPtr->inTraversal = 0;    tsdPtr->serviceMode = TCL_SERVICE_ALL;    return result;}/* *---------------------------------------------------------------------- * * Tcl_ThreadAlert -- * *	This function wakes up the notifier associated with the *	specified thread (if there is one).   * * Results: *	None. * * Side effects: *	None. * *---------------------------------------------------------------------- */voidTcl_ThreadAlert(threadId)    Tcl_ThreadId threadId;	/* Identifier for thread to use. */{    ThreadSpecificData *tsdPtr;    /*     * Find the notifier associated with the specified thread.     * Note that we need to hold the listLock while calling     * Tcl_AlertNotifier to avoid a race condition where     * the specified thread might destroy its notifier.     */    Tcl_MutexLock(&listLock);    for (tsdPtr = firstNotifierPtr; tsdPtr; tsdPtr = tsdPtr->nextPtr) {	if (tsdPtr->threadId == threadId) {	    if (tclStubs.tcl_AlertNotifier) {		tclStubs.tcl_AlertNotifier(tsdPtr->clientData);	    }	    break;	}    }    Tcl_MutexUnlock(&listLock);}

⌨️ 快捷键说明

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