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

📄 tcltimer.c

📁 linux系统下的音频通信
💻 C
📖 第 1 页 / 共 3 页
字号:
 *	idle and after timer lists. * * Results: *	None. * * Side effects: *	May queue an event and update the maximum notifier block time. * *---------------------------------------------------------------------- */static voidTimerCheckProc(data, flags)    ClientData data;		/* Not used. */    int flags;			/* Event flags as passed to Tcl_DoOneEvent. */{    Tcl_Event *timerEvPtr;    Tcl_Time blockTime;    if ((flags & TCL_TIMER_EVENTS) && firstTimerHandlerPtr) {	/*	 * Compute the timeout for the next timer on the list.	 */	TclpGetTime(&blockTime);	blockTime.sec = firstTimerHandlerPtr->time.sec - blockTime.sec;	blockTime.usec = firstTimerHandlerPtr->time.usec - blockTime.usec;	if (blockTime.usec < 0) {	    blockTime.sec -= 1;	    blockTime.usec += 1000000;	}	if (blockTime.sec < 0) {	    blockTime.sec = 0;	    blockTime.usec = 0;	}	/*	 * If the first timer has expired, stick an event on the queue.	 */	if (blockTime.sec == 0 && blockTime.usec == 0 && !timerPending) {	    timerPending = 1;	    timerEvPtr = (Tcl_Event *) ckalloc(sizeof(Tcl_Event));	    timerEvPtr->proc = TimerHandlerEventProc;	    Tcl_QueueEvent(timerEvPtr, TCL_QUEUE_TAIL);	}    }}/* *---------------------------------------------------------------------- * * TimerHandlerEventProc -- * *	This procedure is called by Tcl_ServiceEvent when a timer event *	reaches the front of the event queue.  This procedure handles *	the event by invoking the callbacks for all timers that are *	ready. * * Results: *	Returns 1 if the event was handled, meaning it should be removed *	from the queue.  Returns 0 if the event was not handled, meaning *	it should stay on the queue.  The only time the event isn't *	handled is if the TCL_TIMER_EVENTS flag bit isn't set. * * Side effects: *	Whatever the timer handler callback procedures do. * *---------------------------------------------------------------------- */static intTimerHandlerEventProc(evPtr, flags)    Tcl_Event *evPtr;		/* Event to service. */    int flags;			/* Flags that indicate what events to				 * handle, such as TCL_FILE_EVENTS. */{    TimerHandler *timerHandlerPtr, **nextPtrPtr;    Tcl_Time time;    int currentTimerId;    /*     * Do nothing if timers aren't enabled.  This leaves the event on the     * queue, so we will get to it as soon as ServiceEvents() is called     * with timers enabled.     */    if (!(flags & TCL_TIMER_EVENTS)) {	return 0;    }    /*     * The code below is trickier than it may look, for the following     * reasons:     *     * 1. New handlers can get added to the list while the current     *    one is being processed.  If new ones get added, we don't     *    want to process them during this pass through the list to avoid     *	  starving other event sources.  This is implemented using the     *	  token number in the handler:  new handlers will have a     *    newer token than any of the ones currently on the list.     * 2. The handler can call Tcl_DoOneEvent, so we have to remove     *    the handler from the list before calling it. Otherwise an     *    infinite loop could result.     * 3. Tcl_DeleteTimerHandler can be called to remove an element from     *    the list while a handler is executing, so the list could     *    change structure during the call.     * 4. Because we only fetch the current time before entering the loop,     *    the only way a new timer will even be considered runnable is if     *	  its expiration time is within the same millisecond as the     *	  current time.  This is fairly likely on Windows, since it has     *	  a course granularity clock.  Since timers are placed     *	  on the queue in time order with the most recently created     *    handler appearing after earlier ones with the same expiration     *	  time, we don't have to worry about newer generation timers     *	  appearing before later ones.     */    timerPending = 0;    currentTimerId = lastTimerId;    TclpGetTime(&time);    while (1) {	nextPtrPtr = &firstTimerHandlerPtr;	timerHandlerPtr = firstTimerHandlerPtr;	if (timerHandlerPtr == NULL) {	    break;	}	    	if ((timerHandlerPtr->time.sec > time.sec)		|| ((timerHandlerPtr->time.sec == time.sec)			&& (timerHandlerPtr->time.usec > time.usec))) {	    break;	}	/*	 * Bail out if the next timer is of a newer generation.	 */	if ((currentTimerId - (int)timerHandlerPtr->token) < 0) {	    break;	}	/*	 * Remove the handler from the queue before invoking it,	 * to avoid potential reentrancy problems.	 */	(*nextPtrPtr) = timerHandlerPtr->nextPtr;	(*timerHandlerPtr->proc)(timerHandlerPtr->clientData);	ckfree((char *) timerHandlerPtr);    }    TimerSetupProc(NULL, TCL_TIMER_EVENTS);    return 1;}/* *-------------------------------------------------------------- * * Tcl_DoWhenIdle -- * *	Arrange for proc to be invoked the next time the system is *	idle (i.e., just before the next time that Tcl_DoOneEvent *	would have to wait for something to happen). * * Results: *	None. * * Side effects: *	Proc will eventually be called, with clientData as argument. *	See the manual entry for details. * *-------------------------------------------------------------- */voidTcl_DoWhenIdle(proc, clientData)    Tcl_IdleProc *proc;		/* Procedure to invoke. */    ClientData clientData;	/* Arbitrary value to pass to proc. */{    register IdleHandler *idlePtr;    Tcl_Time blockTime;    if (!initialized) {	InitTimer();    }    idlePtr = (IdleHandler *) ckalloc(sizeof(IdleHandler));    idlePtr->proc = proc;    idlePtr->clientData = clientData;    idlePtr->generation = idleGeneration;    idlePtr->nextPtr = NULL;    if (lastIdlePtr == NULL) {	idleList = idlePtr;    } else {	lastIdlePtr->nextPtr = idlePtr;    }    lastIdlePtr = idlePtr;    blockTime.sec = 0;    blockTime.usec = 0;    Tcl_SetMaxBlockTime(&blockTime);}/* *---------------------------------------------------------------------- * * Tcl_CancelIdleCall -- * *	If there are any when-idle calls requested to a given procedure *	with given clientData, cancel all of them. * * Results: *	None. * * Side effects: *	If the proc/clientData combination were on the when-idle list, *	they are removed so that they will never be called. * *---------------------------------------------------------------------- */voidTcl_CancelIdleCall(proc, clientData)    Tcl_IdleProc *proc;		/* Procedure that was previously registered. */    ClientData clientData;	/* Arbitrary value to pass to proc. */{    register IdleHandler *idlePtr, *prevPtr;    IdleHandler *nextPtr;    for (prevPtr = NULL, idlePtr = idleList; idlePtr != NULL;	    prevPtr = idlePtr, idlePtr = idlePtr->nextPtr) {	while ((idlePtr->proc == proc)		&& (idlePtr->clientData == clientData)) {	    nextPtr = idlePtr->nextPtr;	    ckfree((char *) idlePtr);	    idlePtr = nextPtr;	    if (prevPtr == NULL) {		idleList = idlePtr;	    } else {		prevPtr->nextPtr = idlePtr;	    }	    if (idlePtr == NULL) {		lastIdlePtr = prevPtr;		return;	    }	}    }}/* *---------------------------------------------------------------------- * * TclServiceIdle -- * *	This procedure is invoked by the notifier when it becomes *	idle.  It will invoke all idle handlers that are present at *	the time the call is invoked, but not those added during idle *	processing. * * Results: *	The return value is 1 if TclServiceIdle found something to *	do, otherwise return value is 0. * * Side effects: *	Invokes all pending idle handlers. * *---------------------------------------------------------------------- */intTclServiceIdle(){    IdleHandler *idlePtr;    int oldGeneration;    Tcl_Time blockTime;    if (idleList == NULL) {	return 0;    }    oldGeneration = idleGeneration;    idleGeneration++;    /*     * The code below is trickier than it may look, for the following     * reasons:     *     * 1. New handlers can get added to the list while the current     *    one is being processed.  If new ones get added, we don't     *    want to process them during this pass through the list (want     *    to check for other work to do first).  This is implemented     *    using the generation number in the handler:  new handlers     *    will have a different generation than any of the ones currently     *    on the list.     * 2. The handler can call Tcl_DoOneEvent, so we have to remove     *    the handler from the list before calling it. Otherwise an     *    infinite loop could result.     * 3. Tcl_CancelIdleCall can be called to remove an element from     *    the list while a handler is executing, so the list could     *    change structure during the call.     */    for (idlePtr = idleList;	    ((idlePtr != NULL)		    && ((oldGeneration - idlePtr->generation) >= 0));	    idlePtr = idleList) {	idleList = idlePtr->nextPtr;	if (idleList == NULL) {	    lastIdlePtr = NULL;	}	(*idlePtr->proc)(idlePtr->clientData);	ckfree((char *) idlePtr);    }    if (idleList) {	blockTime.sec = 0;	blockTime.usec = 0;	Tcl_SetMaxBlockTime(&blockTime);    }    return 1;}/* *---------------------------------------------------------------------- * * Tcl_AfterObjCmd -- * *	This procedure is invoked to process the "after" Tcl command. *	See the user documentation for details on what it does. * * Results: *	A standard Tcl result. * * Side effects: *	See the user documentation. * *---------------------------------------------------------------------- */	/* ARGSUSED */intTcl_AfterObjCmd(clientData, interp, objc, objv)    ClientData clientData;	/* Points to the "tclAfter" assocData for				 * this interpreter, or NULL if the assocData				 * hasn't been created yet.*/    Tcl_Interp *interp;		/* Current interpreter. */    int objc;			/* Number of arguments. */    Tcl_Obj *CONST objv[];	/* Argument objects. */{    /*     * The variable below is used to generate unique identifiers for     * after commands.  This id can wrap around, which can potentially     * cause problems.  However, there are not likely to be problems     * in practice, because after commands can only be requested to     * about a month in the future, and wrap-around is unlikely to     * occur in less than about 1-10 years.  Thus it's unlikely that     * any old ids will still be around when wrap-around occurs.     */    static int nextId = 1;    int ms;    AfterInfo *afterPtr;    AfterAssocData *assocPtr = (AfterAssocData *) clientData;    Tcl_CmdInfo cmdInfo;    int length;    char *arg;    int index, result;    static char *subCmds[] = {        "cancel", "idle", "info",        (char *) NULL};    

⌨️ 快捷键说明

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