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

📄 tclnotify.c

📁 linux系统下的音频通信
💻 C
📖 第 1 页 / 共 2 页
字号:
/*  * tclNotify.c -- * *	This file implements the generic portion of the Tcl notifier. *	The notifier is lowest-level part of the event system.  It *	manages an event queue that holds Tcl_Event structures.  The *	platform specific portion of the notifier is defined in the *	tcl*Notify.c files in each platform directory. * * Copyright (c) 1995-1997 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: @(#) tclNotify.c 1.16 97/09/15 15:12:52 */#include "tclInt.h"#include "tclPort.h"/* * The following static indicates whether this module has been initialized. */static int initialized = 0;/* * For each event source (created with Tcl_CreateEventSource) there * is a structure of the following type: */typedef struct EventSource {    Tcl_EventSetupProc *setupProc;    Tcl_EventCheckProc *checkProc;    ClientData clientData;    struct EventSource *nextPtr;} EventSource;/* * The following structure keeps track of the state of the notifier. * The first three elements keep track of the event queue.  In addition to * the first (next to be serviced) and last events in the queue, we keep * track of a "marker" event.  This provides a simple priority mechanism * whereby events can be inserted at the front of the queue but behind all * other high-priority events already in the queue (this is used for things * like a sequence of Enter and Leave events generated during a grab in * Tk). */static struct {    Tcl_Event *firstEventPtr;	/* First pending event, or NULL if none. */    Tcl_Event *lastEventPtr;	/* Last pending event, or NULL if none. */    Tcl_Event *markerEventPtr;	/* Last high-priority event in queue, or				 * NULL if none. */    int serviceMode;		/* One of TCL_SERVICE_NONE or				 * TCL_SERVICE_ALL. */    int blockTimeSet;		/* 0 means there is no maximum block				 * time:  block forever. */    Tcl_Time blockTime;		/* If blockTimeSet is 1, gives the				 * maximum elapsed time for the next block. */    int inTraversal;		/* 1 if Tcl_SetMaxBlockTime is being				 * called during an event source traversal. */    EventSource *firstEventSourcePtr;				/* Pointer to first event source in				 * global list of event sources. */} notifier;/* * Declarations for functions used in this file. */static void	InitNotifier _ANSI_ARGS_((void));static void	NotifierExitHandler _ANSI_ARGS_((ClientData clientData));/* *---------------------------------------------------------------------- * * InitNotifier -- * *	This routine is called to initialize the notifier module. * * Results: *	None. * * Side effects: *	Creates an exit handler and initializes static data. * *---------------------------------------------------------------------- */static voidInitNotifier(){    initialized = 1;    memset(&notifier, 0, sizeof(notifier));    notifier.serviceMode = TCL_SERVICE_NONE;    Tcl_CreateExitHandler(NotifierExitHandler, NULL);}/* *---------------------------------------------------------------------- * * NotifierExitHandler -- * *	This routine is called during Tcl finalization. * * Results: *	None. * * Side effects: *	Clears the notifier intialization flag. * *---------------------------------------------------------------------- */static voidNotifierExitHandler(clientData)    ClientData clientData;  /* Not used. */{    initialized = 0;}/* *---------------------------------------------------------------------- * * Tcl_CreateEventSource -- * *	This procedure is invoked to create a new source of events. *	The source is identified by a procedure that gets invoked *	during Tcl_DoOneEvent to check for events on that source *	and queue them. * * * Results: *	None. * * Side effects: *	SetupProc and checkProc will be invoked each time that Tcl_DoOneEvent *	runs out of things to do.  SetupProc will be invoked before *	Tcl_DoOneEvent calls select or whatever else it uses to wait *	for events.  SetupProc typically calls functions like Tcl_WatchFile *	or Tcl_SetMaxBlockTime to indicate what to wait for. * *	CheckProc is called after select or whatever operation was actually *	used to wait.  It figures out whether anything interesting actually *	happened (e.g. by calling Tcl_FileReady), and then calls *	Tcl_QueueEvent to queue any events that are ready. * *	Each of these procedures is passed two arguments, e.g. *		(*checkProc)(ClientData clientData, int flags)); *	ClientData is the same as the clientData argument here, and flags *	is a combination of things like TCL_FILE_EVENTS that indicates *	what events are of interest:  setupProc and checkProc use flags *	to figure out whether their events are relevant or not. * *---------------------------------------------------------------------- */voidTcl_CreateEventSource(setupProc, checkProc, clientData)    Tcl_EventSetupProc *setupProc;	/* Procedure to invoke to figure out					 * what to wait for. */    Tcl_EventCheckProc *checkProc;	/* Procedure to call after waiting					 * to see what happened. */    ClientData clientData;		/* One-word argument to pass to					 * setupProc and checkProc. */{    EventSource *sourcePtr;    if (!initialized) {	InitNotifier();    }    sourcePtr = (EventSource *) ckalloc(sizeof(EventSource));    sourcePtr->setupProc = setupProc;    sourcePtr->checkProc = checkProc;    sourcePtr->clientData = clientData;    sourcePtr->nextPtr = notifier.firstEventSourcePtr;    notifier.firstEventSourcePtr = sourcePtr;}/* *---------------------------------------------------------------------- * * Tcl_DeleteEventSource -- * *	This procedure is invoked to delete the source of events *	given by proc and clientData. * * Results: *	None. * * Side effects: *	The given event source is cancelled, so its procedure will *	never again be called.  If no such source exists, nothing *	happens. * *---------------------------------------------------------------------- */voidTcl_DeleteEventSource(setupProc, checkProc, clientData)    Tcl_EventSetupProc *setupProc;	/* Procedure to invoke to figure out					 * what to wait for. */    Tcl_EventCheckProc *checkProc;	/* Procedure to call after waiting					 * to see what happened. */    ClientData clientData;		/* One-word argument to pass to					 * setupProc and checkProc. */{    EventSource *sourcePtr, *prevPtr;    for (sourcePtr = notifier.firstEventSourcePtr, prevPtr = NULL;	    sourcePtr != NULL;	    prevPtr = sourcePtr, sourcePtr = sourcePtr->nextPtr) {	if ((sourcePtr->setupProc != setupProc)		|| (sourcePtr->checkProc != checkProc)		|| (sourcePtr->clientData != clientData)) {	    continue;	}	if (prevPtr == NULL) {	    notifier.firstEventSourcePtr = sourcePtr->nextPtr;	} else {	    prevPtr->nextPtr = sourcePtr->nextPtr;	}	ckfree((char *) sourcePtr);	return;    }}/* *---------------------------------------------------------------------- * * Tcl_QueueEvent -- * *	Insert an event into the Tk 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. * *---------------------------------------------------------------------- */voidTcl_QueueEvent(evPtr, position)    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. */{    if (!initialized) {	InitNotifier();    }    if (position == TCL_QUEUE_TAIL) {	/*	 * Append the event on the end of the queue.	 */	evPtr->nextPtr = NULL;	if (notifier.firstEventPtr == NULL) {	    notifier.firstEventPtr = evPtr;	} else {	    notifier.lastEventPtr->nextPtr = evPtr;	}	notifier.lastEventPtr = evPtr;    } else if (position == TCL_QUEUE_HEAD) {	/*	 * Push the event on the head of the queue.	 */	evPtr->nextPtr = notifier.firstEventPtr;	if (notifier.firstEventPtr == NULL) {	    notifier.lastEventPtr = evPtr;	}	    	notifier.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 (notifier.markerEventPtr == NULL) {	    evPtr->nextPtr = notifier.firstEventPtr;	    notifier.firstEventPtr = evPtr;	} else {	    evPtr->nextPtr = notifier.markerEventPtr->nextPtr;	    notifier.markerEventPtr->nextPtr = evPtr;	}	notifier.markerEventPtr = evPtr;	if (evPtr->nextPtr == NULL) {	    notifier.lastEventPtr = evPtr;	}    }}/* *---------------------------------------------------------------------- * * 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. * * 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;    if (!initialized) {	InitNotifier();    }    for (prevPtr = (Tcl_Event *) NULL, evPtr = notifier.firstEventPtr;             evPtr != (Tcl_Event *) NULL;             ) {        if ((*proc) (evPtr, clientData) == 1) {            if (notifier.firstEventPtr == evPtr) {                notifier.firstEventPtr = evPtr->nextPtr;                if (evPtr->nextPtr == (Tcl_Event *) NULL) {                    notifier.lastEventPtr = (Tcl_Event *) NULL;                }            } else {                prevPtr->nextPtr = evPtr->nextPtr;            }            hold = evPtr;            evPtr = evPtr->nextPtr;            ckfree((char *) hold);        } else {            prevPtr = evPtr;            evPtr = evPtr->nextPtr;        }    }}/* *---------------------------------------------------------------------- * * Tcl_ServiceEvent -- * *	Process one event from the event queue, or invoke an *	asynchronous event handler. * * 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;    if (!initialized) {	InitNotifier();    }    /*     * 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.     */    for (evPtr = notifier.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, but 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;	evPtr->proc = NULL;

⌨️ 快捷键说明

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