diff options
Diffstat (limited to 'generic/tclNotify.c')
| -rw-r--r-- | generic/tclNotify.c | 118 | 
1 files changed, 68 insertions, 50 deletions
| diff --git a/generic/tclNotify.c b/generic/tclNotify.c index d8de8d8..e76bca8 100644 --- a/generic/tclNotify.c +++ b/generic/tclNotify.c @@ -13,13 +13,18 @@   *   * See the file "license.terms" for information on usage and redistribution of   * this file, and for a DISCLAIMER OF ALL WARRANTIES. - * - * RCS: @(#) $Id: tclNotify.c,v 1.20 2005/11/02 00:55:06 dkf Exp $   */  #include "tclInt.h" -extern TclStubs tclStubs; +/* + * Module-scope struct of notifier hooks that are checked in the default + * notifier functions (for overriding via Tcl_SetNotifier). + */ + +Tcl_NotifierProcs tclNotifierHooks = { +    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL +};  /*   * For each event source (created with Tcl_CreateEventSource) there is a @@ -90,7 +95,7 @@ TCL_DECLARE_MUTEX(listLock)   */  static void		QueueEvent(ThreadSpecificData *tsdPtr, -			    Tcl_Event* evPtr, Tcl_QueuePosition position); +			    Tcl_Event *evPtr, Tcl_QueuePosition position);  /*   *---------------------------------------------------------------------- @@ -128,7 +133,7 @@ TclInitNotifier(void)  	tsdPtr = TCL_TSD_INIT(&dataKey);  	tsdPtr->threadId = threadId; -	tsdPtr->clientData = tclStubs.tcl_InitNotifier(); +	tsdPtr->clientData = Tcl_InitNotifier();  	tsdPtr->initialized = 1;  	tsdPtr->nextPtr = firstNotifierPtr;  	firstNotifierPtr = tsdPtr; @@ -176,7 +181,7 @@ TclFinalizeNotifier(void)      for (evPtr = tsdPtr->firstEventPtr; evPtr != NULL; ) {  	hold = evPtr;  	evPtr = evPtr->nextPtr; -	ckfree((char *) hold); +	ckfree(hold);      }      tsdPtr->firstEventPtr = NULL;      tsdPtr->lastEventPtr = NULL; @@ -184,9 +189,7 @@ TclFinalizeNotifier(void)      Tcl_MutexLock(&listLock); -    if (tclStubs.tcl_FinalizeNotifier) { -	tclStubs.tcl_FinalizeNotifier(tsdPtr->clientData); -    } +    Tcl_FinalizeNotifier(tsdPtr->clientData);      Tcl_MutexFinalize(&(tsdPtr->queueMutex));      for (prevPtrPtr = &firstNotifierPtr; *prevPtrPtr != NULL;  	    prevPtrPtr = &((*prevPtrPtr)->nextPtr)) { @@ -213,9 +216,8 @@ TclFinalizeNotifier(void)   *	None.   *   * Side effects: - *	Overstomps part of the stub vector. This relies on hooks added to the - *	default functions in case those are called directly (i.e., not through - *	the stub table.) + *	Set the tclNotifierHooks global, which is checked in the default + *	notifier functions.   *   *----------------------------------------------------------------------   */ @@ -224,16 +226,7 @@ void  Tcl_SetNotifier(      Tcl_NotifierProcs *notifierProcPtr)  { -#if !defined(__WIN32__) /* UNIX */ -    tclStubs.tcl_CreateFileHandler = notifierProcPtr->createFileHandlerProc; -    tclStubs.tcl_DeleteFileHandler = notifierProcPtr->deleteFileHandlerProc; -#endif -    tclStubs.tcl_SetTimer = notifierProcPtr->setTimerProc; -    tclStubs.tcl_WaitForEvent = notifierProcPtr->waitForEventProc; -    tclStubs.tcl_InitNotifier = notifierProcPtr->initNotifierProc; -    tclStubs.tcl_FinalizeNotifier = notifierProcPtr->finalizeNotifierProc; -    tclStubs.tcl_AlertNotifier = notifierProcPtr->alertNotifierProc; -    tclStubs.tcl_ServiceModeHook = notifierProcPtr->serviceModeHookProc; +    tclNotifierHooks = *notifierProcPtr;  }  /* @@ -283,7 +276,7 @@ Tcl_CreateEventSource(  				 * checkProc. */  {      ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); -    EventSource *sourcePtr = (EventSource *) ckalloc(sizeof(EventSource)); +    EventSource *sourcePtr = ckalloc(sizeof(EventSource));      sourcePtr->setupProc = setupProc;      sourcePtr->checkProc = checkProc; @@ -304,7 +297,7 @@ Tcl_CreateEventSource(   *	None.   *   * Side effects: - *	The given event source is cancelled, so its function will never again + *	The given event source is canceled, so its function will never again   *	be called. If no such source exists, nothing happens.   *   *---------------------------------------------------------------------- @@ -337,7 +330,7 @@ Tcl_DeleteEventSource(  	} else {  	    prevPtr->nextPtr = sourcePtr->nextPtr;  	} -	ckfree((char *) sourcePtr); +	ckfree(sourcePtr);  	return;      }  } @@ -360,7 +353,7 @@ Tcl_DeleteEventSource(  void  Tcl_QueueEvent( -    Tcl_Event* evPtr,		/* Event to add to queue. The storage space +    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 @@ -369,6 +362,7 @@ Tcl_QueueEvent(  				 * TCL_QUEUE_MARK. */  {      ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); +      QueueEvent(tsdPtr, evPtr, position);  } @@ -417,6 +411,8 @@ Tcl_ThreadQueueEvent(      if (tsdPtr) {  	QueueEvent(tsdPtr, evPtr, position); +    } else { +	ckfree(evPtr);      }      Tcl_MutexUnlock(&listLock);  } @@ -520,29 +516,59 @@ QueueEvent(  void  Tcl_DeleteEvents(      Tcl_EventDeleteProc *proc,	/* The function to call. */ -    ClientData clientData)    	/* The type-specific data. */ +    ClientData clientData)	/* The type-specific data. */  { -    Tcl_Event *evPtr, *prevPtr, *hold; +    Tcl_Event *evPtr;		/* Pointer to the event being examined */ +    Tcl_Event *prevPtr;		/* Pointer to evPtr's predecessor, or NULL if +				 * evPtr designates the first event in the +				 * queue for the thread. */ +    Tcl_Event *hold;      ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);      Tcl_MutexLock(&(tsdPtr->queueMutex)); -    for (prevPtr=NULL, evPtr=tsdPtr->firstEventPtr; evPtr!=NULL; ) { -	if ((*proc) (evPtr, clientData) == 1) { -	    if (tsdPtr->firstEventPtr == evPtr) { + +    /* +     * Walk the queue of events for the thread, applying 'proc' to each to +     * decide whether to eliminate the event. +     */ + +    prevPtr = NULL; +    evPtr = tsdPtr->firstEventPtr; +    while (evPtr != NULL) { +	if (proc(evPtr, clientData) == 1) { +	    /* +	     * This event should be deleted. Unlink it. +	     */ + +	    if (prevPtr == NULL) {  		tsdPtr->firstEventPtr = evPtr->nextPtr;  	    } else {  		prevPtr->nextPtr = evPtr->nextPtr;  	    } + +	    /* +	     * Update 'last' and 'marker' events if either has been deleted. +	     */ +  	    if (evPtr->nextPtr == NULL) {  		tsdPtr->lastEventPtr = prevPtr;  	    }  	    if (tsdPtr->markerEventPtr == evPtr) {  		tsdPtr->markerEventPtr = prevPtr;  	    } + +	    /* +	     * Delete the event data structure. +	     */ +  	    hold = evPtr;  	    evPtr = evPtr->nextPtr; -	    ckfree((char *) hold); +	    ckfree(hold);  	} else { +	    /* +	     * Event is to be retained. +	     */ +  	    prevPtr = evPtr;  	    evPtr = evPtr->nextPtr;  	} @@ -641,7 +667,7 @@ Tcl_ServiceEvent(  	 */  	Tcl_MutexUnlock(&(tsdPtr->queueMutex)); -	result = (*proc)(evPtr, flags); +	result = proc(evPtr, flags);  	Tcl_MutexLock(&(tsdPtr->queueMutex));  	if (result) { @@ -676,7 +702,7 @@ Tcl_ServiceEvent(  		}  	    }  	    if (evPtr) { -		ckfree((char *) evPtr); +		ckfree(evPtr);  	    }  	    Tcl_MutexUnlock(&(tsdPtr->queueMutex));  	    return 1; @@ -743,9 +769,7 @@ Tcl_SetServiceMode(      oldMode = tsdPtr->serviceMode;      tsdPtr->serviceMode = mode; -    if (tclStubs.tcl_ServiceModeHook) { -	tclStubs.tcl_ServiceModeHook(mode); -    } +    Tcl_ServiceModeHook(mode);      return oldMode;  } @@ -770,7 +794,7 @@ Tcl_SetServiceMode(  void  Tcl_SetMaxBlockTime( -    Tcl_Time *timePtr)		/* Specifies a maximum elapsed time for the +    const Tcl_Time *timePtr)		/* Specifies a maximum elapsed time for the  				 * next blocking operation in the event  				 * tsdPtr-> */  { @@ -789,11 +813,7 @@ Tcl_SetMaxBlockTime(       */      if (!tsdPtr->inTraversal) { -	if (tsdPtr->blockTimeSet) { -	    Tcl_SetTimer(&tsdPtr->blockTime); -	} else { -	    Tcl_SetTimer(NULL); -	} +	Tcl_SetTimer(&tsdPtr->blockTime);      }  } @@ -907,7 +927,7 @@ Tcl_DoOneEvent(  	for (sourcePtr = tsdPtr->firstEventSourcePtr; sourcePtr != NULL;  		sourcePtr = sourcePtr->nextPtr) {  	    if (sourcePtr->setupProc) { -		(sourcePtr->setupProc)(sourcePtr->clientData, flags); +		sourcePtr->setupProc(sourcePtr->clientData, flags);  	    }  	}  	tsdPtr->inTraversal = 0; @@ -936,7 +956,7 @@ Tcl_DoOneEvent(  	for (sourcePtr = tsdPtr->firstEventSourcePtr; sourcePtr != NULL;  		sourcePtr = sourcePtr->nextPtr) {  	    if (sourcePtr->checkProc) { -		(sourcePtr->checkProc)(sourcePtr->clientData, flags); +		sourcePtr->checkProc(sourcePtr->clientData, flags);  	    }  	} @@ -1046,13 +1066,13 @@ Tcl_ServiceAll(void)      for (sourcePtr = tsdPtr->firstEventSourcePtr; sourcePtr != NULL;  	    sourcePtr = sourcePtr->nextPtr) {  	if (sourcePtr->setupProc) { -	    (sourcePtr->setupProc)(sourcePtr->clientData, TCL_ALL_EVENTS); +	    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); +	    sourcePtr->checkProc(sourcePtr->clientData, TCL_ALL_EVENTS);  	}      } @@ -1105,9 +1125,7 @@ Tcl_ThreadAlert(      Tcl_MutexLock(&listLock);      for (tsdPtr = firstNotifierPtr; tsdPtr; tsdPtr = tsdPtr->nextPtr) {  	if (tsdPtr->threadId == threadId) { -	    if (tclStubs.tcl_AlertNotifier) { -		tclStubs.tcl_AlertNotifier(tsdPtr->clientData); -	    } +	    Tcl_AlertNotifier(tsdPtr->clientData);  	    break;  	}      } | 
