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

📄 tcltimer.c

📁 linux系统下的音频通信
💻 C
📖 第 1 页 / 共 3 页
字号:
/*  * tclTimer.c -- * *	This file provides timer event management facilities for Tcl, *	including the "after" command. * * Copyright (c) 1997 by Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * * SCCS: @(#) tclTimer.c 1.9 97/07/29 16:21:53 */#include "tclInt.h"#include "tclPort.h"/* * This flag indicates whether this module has been initialized. */static int initialized = 0;/* * For each timer callback that's pending there is one record of the following * type.  The normal handlers (created by Tcl_CreateTimerHandler) are chained * together in a list sorted by time (earliest event first). */typedef struct TimerHandler {    Tcl_Time time;			/* When timer is to fire. */    Tcl_TimerProc *proc;		/* Procedure to call. */    ClientData clientData;		/* Argument to pass to proc. */    Tcl_TimerToken token;		/* Identifies handler so it can be					 * deleted. */    struct TimerHandler *nextPtr;	/* Next event in queue, or NULL for					 * end of queue. */} TimerHandler;static TimerHandler *firstTimerHandlerPtr = NULL;					/* First event in queue. */static int lastTimerId;			/* Timer identifier of most recently					 * created timer. */static int timerPending;		/* 1 if a timer event is in the queue. *//* * The data structure below is used by the "after" command to remember * the command to be executed later.  All of the pending "after" commands * for an interpreter are linked together in a list. */typedef struct AfterInfo {    struct AfterAssocData *assocPtr;				/* Pointer to the "tclAfter" assocData for				 * the interp in which command will be				 * executed. */    char *command;		/* Command to execute.  Malloc'ed, so must				 * be freed when structure is deallocated. */    int id;			/* Integer identifier for command;  used to				 * cancel it. */    Tcl_TimerToken token;	/* Used to cancel the "after" command.  NULL				 * means that the command is run as an				 * idle handler rather than as a timer				 * handler.  NULL means this is an "after				 * idle" handler rather than a                                 * timer handler. */    struct AfterInfo *nextPtr;	/* Next in list of all "after" commands for				 * this interpreter. */} AfterInfo;/* * One of the following structures is associated with each interpreter * for which an "after" command has ever been invoked.  A pointer to * this structure is stored in the AssocData for the "tclAfter" key. */typedef struct AfterAssocData {    Tcl_Interp *interp;		/* The interpreter for which this data is				 * registered. */    AfterInfo *firstAfterPtr;	/* First in list of all "after" commands				 * still pending for this interpreter, or				 * NULL if none. */} AfterAssocData;/* * There is one of the following structures for each of the * handlers declared in a call to Tcl_DoWhenIdle.  All of the * currently-active handlers are linked together into a list. */typedef struct IdleHandler {    Tcl_IdleProc (*proc);	/* Procedure to call. */    ClientData clientData;	/* Value to pass to proc. */    int generation;		/* Used to distinguish older handlers from				 * recently-created ones. */    struct IdleHandler *nextPtr;/* Next in list of active handlers. */} IdleHandler;static IdleHandler *idleList;				/* First in list of all idle handlers. */static IdleHandler *lastIdlePtr;				/* Last in list (or NULL for empty list). */static int idleGeneration;	/* Used to fill in the "generation" fields				 * of IdleHandler structures.  Increments				 * each time Tcl_DoOneEvent starts calling				 * idle handlers, so that all old handlers				 * can be called without calling any of the				 * new ones created by old ones. *//* * Prototypes for procedures referenced only in this file: */static void		AfterCleanupProc _ANSI_ARGS_((ClientData clientData,			    Tcl_Interp *interp));static void		AfterProc _ANSI_ARGS_((ClientData clientData));static void		FreeAfterPtr _ANSI_ARGS_((AfterInfo *afterPtr));static AfterInfo *	GetAfterEvent _ANSI_ARGS_((AfterAssocData *assocPtr,			    char *string));static void		InitTimer _ANSI_ARGS_((void));static void		TimerExitProc _ANSI_ARGS_((ClientData clientData));static int		TimerHandlerEventProc _ANSI_ARGS_((Tcl_Event *evPtr,			    int flags));static void		TimerCheckProc _ANSI_ARGS_((ClientData clientData,			    int flags));static void		TimerSetupProc _ANSI_ARGS_((ClientData clientData,			    int flags));/* *---------------------------------------------------------------------- * * InitTimer -- * *	This function initializes the timer module. * * Results: *	None. * * Side effects: *	Registers the idle and timer event sources. * *---------------------------------------------------------------------- */static voidInitTimer(){    initialized = 1;    lastTimerId = 0;    timerPending = 0;    idleGeneration = 0;    firstTimerHandlerPtr = NULL;    lastIdlePtr = NULL;    idleList = NULL;    Tcl_CreateEventSource(TimerSetupProc, TimerCheckProc, NULL);    Tcl_CreateExitHandler(TimerExitProc, NULL);}/* *---------------------------------------------------------------------- * * TimerExitProc -- * *	This function is call at exit or unload time to remove the *	timer and idle event sources. * * Results: *	None. * * Side effects: *	Removes the timer and idle event sources. * *---------------------------------------------------------------------- */static voidTimerExitProc(clientData)    ClientData clientData;	/* Not used. */{    Tcl_DeleteEventSource(TimerSetupProc, TimerCheckProc, NULL);    initialized = 0;}/* *-------------------------------------------------------------- * * Tcl_CreateTimerHandler -- * *	Arrange for a given procedure to be invoked at a particular *	time in the future. * * Results: *	The return value is a token for the timer event, which *	may be used to delete the event before it fires. * * Side effects: *	When milliseconds have elapsed, proc will be invoked *	exactly once. * *-------------------------------------------------------------- */Tcl_TimerTokenTcl_CreateTimerHandler(milliseconds, proc, clientData)    int milliseconds;		/* How many milliseconds to wait				 * before invoking proc. */    Tcl_TimerProc *proc;	/* Procedure to invoke. */    ClientData clientData;	/* Arbitrary data to pass to proc. */{    register TimerHandler *timerHandlerPtr, *tPtr2, *prevPtr;    Tcl_Time time;    if (!initialized) {	InitTimer();    }    timerHandlerPtr = (TimerHandler *) ckalloc(sizeof(TimerHandler));    /*     * Compute when the event should fire.     */    TclpGetTime(&time);    timerHandlerPtr->time.sec = time.sec + milliseconds/1000;    timerHandlerPtr->time.usec = time.usec + (milliseconds%1000)*1000;    if (timerHandlerPtr->time.usec >= 1000000) {	timerHandlerPtr->time.usec -= 1000000;	timerHandlerPtr->time.sec += 1;    }        /*     * Fill in other fields for the event.     */    timerHandlerPtr->proc = proc;    timerHandlerPtr->clientData = clientData;    lastTimerId++;    timerHandlerPtr->token = (Tcl_TimerToken) lastTimerId;    /*     * Add the event to the queue in the correct position     * (ordered by event firing time).     */    for (tPtr2 = firstTimerHandlerPtr, prevPtr = NULL; tPtr2 != NULL;	    prevPtr = tPtr2, tPtr2 = tPtr2->nextPtr) {	if ((tPtr2->time.sec > timerHandlerPtr->time.sec)		|| ((tPtr2->time.sec == timerHandlerPtr->time.sec)		&& (tPtr2->time.usec > timerHandlerPtr->time.usec))) {	    break;	}    }    timerHandlerPtr->nextPtr = tPtr2;    if (prevPtr == NULL) {	firstTimerHandlerPtr = timerHandlerPtr;    } else {	prevPtr->nextPtr = timerHandlerPtr;    }    TimerSetupProc(NULL, TCL_ALL_EVENTS);    return timerHandlerPtr->token;}/* *-------------------------------------------------------------- * * Tcl_DeleteTimerHandler -- * *	Delete a previously-registered timer handler. * * Results: *	None. * * Side effects: *	Destroy the timer callback identified by TimerToken, *	so that its associated procedure will not be called. *	If the callback has already fired, or if the given *	token doesn't exist, then nothing happens. * *-------------------------------------------------------------- */voidTcl_DeleteTimerHandler(token)    Tcl_TimerToken token;	/* Result previously returned by				 * Tcl_DeleteTimerHandler. */{    register TimerHandler *timerHandlerPtr, *prevPtr;    for (timerHandlerPtr = firstTimerHandlerPtr, prevPtr = NULL;	    timerHandlerPtr != NULL; prevPtr = timerHandlerPtr,	    timerHandlerPtr = timerHandlerPtr->nextPtr) {	if (timerHandlerPtr->token != token) {	    continue;	}	if (prevPtr == NULL) {	    firstTimerHandlerPtr = timerHandlerPtr->nextPtr;	} else {	    prevPtr->nextPtr = timerHandlerPtr->nextPtr;	}	ckfree((char *) timerHandlerPtr);	return;    }}/* *---------------------------------------------------------------------- * * TimerSetupProc -- * *	This function is called by Tcl_DoOneEvent to setup the timer *	event source for before blocking.  This routine checks both the *	idle and after timer lists. * * Results: *	None. * * Side effects: *	May update the maximum notifier block time. * *---------------------------------------------------------------------- */static voidTimerSetupProc(data, flags)    ClientData data;		/* Not used. */    int flags;			/* Event flags as passed to Tcl_DoOneEvent. */{    Tcl_Time blockTime;    if (((flags & TCL_IDLE_EVENTS) && idleList)	    || ((flags & TCL_TIMER_EVENTS) && timerPending)) {	/*	 * There is an idle handler or a pending timer event, so just poll.	 */	blockTime.sec = 0;	blockTime.usec = 0;    } else 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;	}    } else {	return;    }	    Tcl_SetMaxBlockTime(&blockTime);}/* *---------------------------------------------------------------------- * * TimerCheckProc -- * *	This function is called by Tcl_DoOneEvent to check the timer *	event source for events.  This routine checks both the

⌨️ 快捷键说明

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