From 1f27bcb487508323c68e02927575ef9717428b9c Mon Sep 17 00:00:00 2001 From: dkf Date: Thu, 28 Apr 2005 08:37:01 +0000 Subject: Fix [1191097], factor, and tidy up. --- ChangeLog | 6 + macosx/tkMacOSXNotify.c | 400 +++++++++++++++++++++++++----------------------- 2 files changed, 214 insertions(+), 192 deletions(-) diff --git a/ChangeLog b/ChangeLog index 95e8be2..16146ef 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2005-04-28 Donal K. Fellows + + * macosx/tkMacOSXNotify.c (TkMacOSXWaitForEvent): Fix for typo in + waitTime computation. [Bug 1191097] + (AlertNotifier): Factor out the core of the notifier alerting code. + 2005-04-25 Daniel Steffen * macosx/tkMacOSXNotify.c: sync with tclUnixNotfy.c changes since diff --git a/macosx/tkMacOSXNotify.c b/macosx/tkMacOSXNotify.c index 5dd6743..abf83b4 100644 --- a/macosx/tkMacOSXNotify.c +++ b/macosx/tkMacOSXNotify.c @@ -4,7 +4,7 @@ * This file contains the implementation of a merged * Carbon/select-based notifier, which is the lowest-level part * of the Tcl event loop. This file works together with - * ../generic/tclNotify.c. + * generic/tclNotify.c. * * Copyright (c) 1995-1997 Sun Microsystems, Inc. * Copyright 2001, Apple Computer, Inc. @@ -12,7 +12,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tkMacOSXNotify.c,v 1.9 2005/04/26 00:46:53 das Exp $ + * RCS: @(#) $Id: tkMacOSXNotify.c,v 1.10 2005/04/28 08:37:01 dkf Exp $ */ #include "tclInt.h" @@ -79,7 +79,7 @@ typedef struct SelectMasks { typedef struct ThreadSpecificData { FileHandler *firstFileHandlerPtr; /* Pointer to head of file handler list. */ - + SelectMasks checkMasks; /* This structure is used to build up the masks * to be used in the next call to select. * Bits are set in response to calls to @@ -90,25 +90,25 @@ typedef struct ThreadSpecificData { int numFdBits; /* Number of valid bits in checkMasks * (one more than highest fd for which * Tcl_WatchFile has been called). */ - int isMainLoop; /* Is this the main Carbon Loop (in which case - * we will call RNE in the actual wait... */ + int isMainLoop; /* Is this the main Carbon Loop (in which case + * we will call RNE in the actual wait... */ int onList; /* True if it is in this list */ unsigned int pollState; /* pollState is used to implement a polling * handshake between each thread and the * notifier thread. Bits defined below. */ struct ThreadSpecificData *nextPtr, *prevPtr; - /* All threads that are currently waiting on - * an event have their ThreadSpecificData - * structure on a doubly-linked listed formed - * from these pointers. You must hold the - * notifierMutex lock before accessing these - * fields. */ - Tcl_Condition waitCV; /* Any other thread alerts a notifier + /* All threads that are currently waiting on + * an event have their ThreadSpecificData + * structure on a doubly-linked listed formed + * from these pointers. You must hold the + * notifierMutex lock before accessing these + * fields. */ + Tcl_Condition waitCV; /* Any other thread alerts a notifier * that an event is ready to be processed * by signaling this condition variable. */ - int eventReady; /* True if an event is ready to be processed. - * Used as condition flag together with - * waitCV above. */ + int eventReady; /* True if an event is ready to be processed. + * Used as condition flag together with + * waitCV above. */ } ThreadSpecificData; static Tcl_ThreadDataKey dataKey; @@ -184,27 +184,29 @@ static Tcl_ThreadId notifierThread; * Static routines defined in this file. */ -static void NotifierThreadProc _ANSI_ARGS_((ClientData clientData)); -static int FileHandlerEventProc _ANSI_ARGS_((Tcl_Event *evPtr, - int flags)); - -void TkMacOSXSetTimer(Tcl_Time *timePtr); -void TkMacOSXCreateFileHandler(int fd, int mask, Tcl_FileProc *proc, ClientData clientData); -void TkMacOSXDeleteFileHandler(int fd); -int TkMacOSXWaitForEvent(Tcl_Time *timePtr); -void TkMacOSXAlertNotifier(ClientData clientData); -ClientData TkMacOSXInitNotifier(); -void TkMacOSXFinalizeNotifier(ClientData clientData); -void TkMacOSXServiceModeHook(int mode); -EventRef TkMacOSXCreateFakeEvent (); +static void NotifierThreadProc(ClientData clientData); +static int FileHandlerEventProc(Tcl_Event *evPtr, int flags); +static void AlertNotifier(ThreadSpecificData *tsdPtr); + +/* DKF: Should these be static? */ +void TkMacOSXSetTimer(Tcl_Time *timePtr); +void TkMacOSXCreateFileHandler(int fd, int mask, Tcl_FileProc *proc, + ClientData clientData); +void TkMacOSXDeleteFileHandler(int fd); +int TkMacOSXWaitForEvent(Tcl_Time *timePtr); +void TkMacOSXAlertNotifier(ClientData clientData); +ClientData TkMacOSXInitNotifier(); +void TkMacOSXFinalizeNotifier(ClientData clientData); +void TkMacOSXServiceModeHook(int mode); +EventRef TkMacOSXCreateFakeEvent(); /* *---------------------------------------------------------------------- * * Tk_MacOSXSetupTkNotifier -- * * Replaces the Tcl notifier (from tclUnixNotfy.c) with - * the Mac notifier that melds the Unix select based notifer - * with the Carbon event handling side of the Tk notifier. + * the Mac notifier that melds the Unix select based notifer + * with the Carbon event handling side of the Tk notifier. * * Results: * Replaces the notifier callbacks with MacOS X specific ones. @@ -220,14 +222,14 @@ Tk_MacOSXSetupTkNotifier() { EventQueueRef mainEventQueue; Tcl_NotifierProcs macNotifierProcs = { - TkMacOSXSetTimer, - TkMacOSXWaitForEvent, - TkMacOSXCreateFileHandler, - TkMacOSXDeleteFileHandler, - TkMacOSXInitNotifier, - TkMacOSXFinalizeNotifier, - TkMacOSXAlertNotifier, - TkMacOSXServiceModeHook + TkMacOSXSetTimer, + TkMacOSXWaitForEvent, + TkMacOSXCreateFileHandler, + TkMacOSXDeleteFileHandler, + TkMacOSXInitNotifier, + TkMacOSXFinalizeNotifier, + TkMacOSXAlertNotifier, + TkMacOSXServiceModeHook }; /* @@ -235,7 +237,7 @@ Tk_MacOSXSetupTkNotifier() */ TclFinalizeNotifier(); - + Tcl_SetNotifier(&macNotifierProcs); /* HACK ALERT: There is a bug in Jaguar where when it goes to make @@ -245,9 +247,9 @@ Tk_MacOSXSetupTkNotifier() * the main thread. Calling GetMainEventQueue will force this to * happen. */ - + mainEventQueue = GetMainEventQueue(); - + /* * Tcl_SetNotifier doesn't call the TclInitNotifier * so we call it now. If we don't do this the @@ -288,16 +290,16 @@ TkMacOSXInitNotifier() Tcl_MutexLock(¬ifierMutex); if (notifierCount == 0) { if (Tcl_CreateThread(¬ifierThread, NotifierThreadProc, NULL, - TCL_THREAD_STACK_DEFAULT, TCL_THREAD_NOFLAGS) != TCL_OK) { + TCL_THREAD_STACK_DEFAULT, TCL_THREAD_NOFLAGS) != TCL_OK) { Tcl_Panic("Tcl_InitNotifier: unable to start notifier thread"); } } notifierCount++; - + if (GetCurrentEventLoop() == GetMainEventLoop()) { - tsdPtr->isMainLoop = 1; + tsdPtr->isMainLoop = 1; } else { - tsdPtr->isMainLoop = 0; + tsdPtr->isMainLoop = 0; } /* @@ -349,7 +351,7 @@ TkMacOSXFinalizeNotifier(clientData) Tcl_Panic("Tcl_FinalizeNotifier: notifier pipe not initialized"); } - /* + /* * Send "q" message to the notifier thread so that it will * terminate. The notifier will return from its call to select() * and notice that a "q" message has arrived, it will then close @@ -402,20 +404,49 @@ TkMacOSXAlertNotifier(clientData) ThreadSpecificData *tsdPtr = (ThreadSpecificData *) clientData; Tcl_MutexLock(¬ifierMutex); tsdPtr->eventReady = 1; + AlertNotifier(tsdPtr); + Tcl_MutexUnlock(¬ifierMutex); +} + +/* + *---------------------------------------------------------------------- + * + * AlertNotifier -- + * + * The core of the notifier alerting scheme. Either we wake up + * the main event loop and stuff the event to it, or we signal + * the thread's condition variable. Note that callers are + * responsible for locking the right mutexes, managing the rest + * of the notifier state, etc. The thread to alert is determined + * by whose tsdPtr we actually have as our argument. The only + * expected callers are TkMacOSXAlertNotifier() and + * NotifierThreadProc(), both of which take appropriate + * precautions. + * + * Results: + * none + * + * Side effects: + * A notifier is alerted. + * + *---------------------------------------------------------------------- + */ + +static void +AlertNotifier(tsdPtr) + ThreadSpecificData *tsdPtr; +{ if (tsdPtr->isMainLoop) { - OSErr err; - - /* We need to wake up the main loop, and let it have the event. */ - EventRef fakeEvent = TkMacOSXCreateFakeEvent(); - EventQueueRef mainEventQueue = GetMainEventQueue(); - - err = PostEventToQueue(mainEventQueue, fakeEvent, - kEventPriorityHigh); - ReleaseEvent(fakeEvent); + /* We need to wake up the main loop, and let it have the event. */ + EventRef fakeEvent = TkMacOSXCreateFakeEvent(); + EventQueueRef mainEventQueue = GetMainEventQueue(); + OSErr err; + + err = PostEventToQueue(mainEventQueue, fakeEvent, kEventPriorityHigh); + ReleaseEvent(fakeEvent); } else { - Tcl_ConditionNotify(&tsdPtr->waitCV); + Tcl_ConditionNotify(&tsdPtr->waitCV); } - Tcl_MutexUnlock(¬ifierMutex); } /* @@ -445,7 +476,6 @@ TkMacOSXSetTimer(timePtr) * because the only event loop is via Tcl_DoOneEvent, which passes * timeout values to Tcl_WaitForEvent. */ - } /* @@ -502,7 +532,7 @@ TkMacOSXCreateFileHandler(fd, mask, proc, clientData) FileHandler *filePtr; for (filePtr = tsdPtr->firstFileHandlerPtr; filePtr != NULL; - filePtr = filePtr->nextPtr) { + filePtr = filePtr->nextPtr) { if (filePtr->fd == fd) { break; } @@ -522,20 +552,20 @@ TkMacOSXCreateFileHandler(fd, mask, proc, clientData) * Update the check masks for this file. */ - if ( mask & TCL_READABLE ) { - FD_SET( fd, &(tsdPtr->checkMasks.readable) ); + if (mask & TCL_READABLE) { + FD_SET(fd, &(tsdPtr->checkMasks.readable)); } else { - FD_CLR( fd, &(tsdPtr->checkMasks.readable) ); + FD_CLR(fd, &(tsdPtr->checkMasks.readable)); } - if ( mask & TCL_WRITABLE ) { - FD_SET( fd, &(tsdPtr->checkMasks.writable) ); + if (mask & TCL_WRITABLE) { + FD_SET(fd, &(tsdPtr->checkMasks.writable)); } else { - FD_CLR( fd, &(tsdPtr->checkMasks.writable) ); + FD_CLR(fd, &(tsdPtr->checkMasks.writable)); } - if ( mask & TCL_EXCEPTION ) { - FD_SET( fd, &(tsdPtr->checkMasks.exceptional) ); + if (mask & TCL_EXCEPTION) { + FD_SET(fd, &(tsdPtr->checkMasks.exceptional)); } else { - FD_CLR( fd, &(tsdPtr->checkMasks.exceptional) ); + FD_CLR(fd, &(tsdPtr->checkMasks.exceptional)); } if (tsdPtr->numFdBits <= fd) { tsdPtr->numFdBits = fd+1; @@ -586,13 +616,13 @@ TkMacOSXDeleteFileHandler(fd) */ if (filePtr->mask & TCL_READABLE) { - FD_CLR( fd, &(tsdPtr->checkMasks.readable) ); + FD_CLR(fd, &(tsdPtr->checkMasks.readable)); } if (filePtr->mask & TCL_WRITABLE) { - FD_CLR( fd, &(tsdPtr->checkMasks.writable) ); + FD_CLR(fd, &(tsdPtr->checkMasks.writable)); } if (filePtr->mask & TCL_EXCEPTION) { - FD_CLR( fd, &(tsdPtr->checkMasks.exceptional) ); + FD_CLR(fd, &(tsdPtr->checkMasks.exceptional)); } /* @@ -602,9 +632,9 @@ TkMacOSXDeleteFileHandler(fd) if (fd+1 == tsdPtr->numFdBits) { tsdPtr->numFdBits = 0; for (i = fd-1; i >= 0; i--) { - if ( FD_ISSET( i, &(tsdPtr->checkMasks.readable) ) - || FD_ISSET( i, &(tsdPtr->checkMasks.writable) ) - || FD_ISSET( i, &(tsdPtr->checkMasks.exceptional ) ) ) { + if (FD_ISSET(i, &(tsdPtr->checkMasks.readable)) + || FD_ISSET(i, &(tsdPtr->checkMasks.writable)) + || FD_ISSET(i, &(tsdPtr->checkMasks.exceptional))) { tsdPtr->numFdBits = i+1; break; } @@ -669,7 +699,7 @@ FileHandlerEventProc(evPtr, flags) tsdPtr = TCL_TSD_INIT(&dataKey); for (filePtr = tsdPtr->firstFileHandlerPtr; filePtr != NULL; - filePtr = filePtr->nextPtr) { + filePtr = filePtr->nextPtr) { if (filePtr->fd != fileEvPtr->fd) { continue; } @@ -733,24 +763,24 @@ TkMacOSXWaitForEvent(timePtr) * forever. */ - if (timePtr) { + if (timePtr != NULL) { /* TIP #233 (Virtualized Time). Is virtual time in effect ? * And do we actually have something to scale ? If yes to both * then we call the handler to do this scaling */ - myTime.sec = timePtr->sec; + myTime.sec = timePtr->sec; myTime.usec = timePtr->usec; if (myTime.sec != 0 || myTime.usec != 0) { - Tcl_ScaleTimeProc* tclScaleTimeProcPtr; - ClientData tclTimeClientData; - Tcl_QueryTimeProc(NULL, &tclScaleTimeProcPtr, &tclTimeClientData); - + Tcl_ScaleTimeProc* tclScaleTimeProcPtr; + ClientData tclTimeClientData; + + Tcl_QueryTimeProc(NULL, &tclScaleTimeProcPtr, &tclTimeClientData); (*tclScaleTimeProcPtr) (&myTime, tclTimeClientData); } myTimePtr = &myTime; } else { - myTimePtr = NULL; + myTimePtr = NULL; } /* @@ -778,46 +808,45 @@ TkMacOSXWaitForEvent(timePtr) } if (waitForFiles) { - /* - * Add the ThreadSpecificData structure of this thread to the list - * of ThreadSpecificData structures of all threads that are waiting - * on file events. - */ - - - tsdPtr->nextPtr = waitingListPtr; - if (waitingListPtr) { - waitingListPtr->prevPtr = tsdPtr; - } - tsdPtr->prevPtr = 0; - waitingListPtr = tsdPtr; + /* + * Add the ThreadSpecificData structure of this thread to the list + * of ThreadSpecificData structures of all threads that are waiting + * on file events. + */ + + tsdPtr->nextPtr = waitingListPtr; + if (waitingListPtr) { + waitingListPtr->prevPtr = tsdPtr; + } + tsdPtr->prevPtr = 0; + waitingListPtr = tsdPtr; tsdPtr->onList = 1; - + write(triggerPipe, "", 1); } - FD_ZERO( &(tsdPtr->readyMasks.readable) ); - FD_ZERO( &(tsdPtr->readyMasks.writable) ); - FD_ZERO( &(tsdPtr->readyMasks.exceptional) ); + FD_ZERO(&(tsdPtr->readyMasks.readable)); + FD_ZERO(&(tsdPtr->readyMasks.writable)); + FD_ZERO(&(tsdPtr->readyMasks.exceptional)); if (!tsdPtr->eventReady) { - if (!tsdPtr->isMainLoop) { - Tcl_ConditionWait(&tsdPtr->waitCV, ¬ifierMutex, myTimePtr); - } else { - OSErr err; - EventRef eventRef; - EventTime waitTime; - - if (timePtr == NULL) { - waitTime = kEventDurationForever; - } else { - waitTime = myTimePtr->sec * kEventDurationSecond - + myTimePtr->usec * kEventDurationMicrosecond; - } - Tcl_MutexUnlock(¬ifierMutex); - err = ReceiveNextEvent(0, NULL, waitTime, false, &eventRef); - Tcl_MutexLock(¬ifierMutex); - } + if (!tsdPtr->isMainLoop) { + Tcl_ConditionWait(&tsdPtr->waitCV, ¬ifierMutex, myTimePtr); + } else { + OSErr err; + EventRef eventRef; + EventTime waitTime; + + if (myTimePtr == NULL) { + waitTime = kEventDurationForever; + } else { + waitTime = myTimePtr->sec * kEventDurationSecond + + myTimePtr->usec * kEventDurationMicrosecond; + } + Tcl_MutexUnlock(¬ifierMutex); + err = ReceiveNextEvent(0, NULL, waitTime, false, &eventRef); + Tcl_MutexLock(¬ifierMutex); + } } tsdPtr->eventReady = 0; @@ -829,35 +858,34 @@ TkMacOSXWaitForEvent(timePtr) * which the notifier thread was still doing a select on. */ - if (tsdPtr->prevPtr) { - tsdPtr->prevPtr->nextPtr = tsdPtr->nextPtr; - } else { - waitingListPtr = tsdPtr->nextPtr; - } - if (tsdPtr->nextPtr) { - tsdPtr->nextPtr->prevPtr = tsdPtr->prevPtr; - } - tsdPtr->nextPtr = tsdPtr->prevPtr = NULL; + if (tsdPtr->prevPtr) { + tsdPtr->prevPtr->nextPtr = tsdPtr->nextPtr; + } else { + waitingListPtr = tsdPtr->nextPtr; + } + if (tsdPtr->nextPtr) { + tsdPtr->nextPtr->prevPtr = tsdPtr->prevPtr; + } + tsdPtr->nextPtr = tsdPtr->prevPtr = NULL; tsdPtr->onList = 0; write(triggerPipe, "", 1); } - /* * Queue all detected file events before returning. */ for (filePtr = tsdPtr->firstFileHandlerPtr; (filePtr != NULL); - filePtr = filePtr->nextPtr) { + filePtr = filePtr->nextPtr) { mask = 0; - if ( FD_ISSET( filePtr->fd, &(tsdPtr->readyMasks.readable) ) ) { + if (FD_ISSET(filePtr->fd, &(tsdPtr->readyMasks.readable))) { mask |= TCL_READABLE; } - if ( FD_ISSET( filePtr->fd, &(tsdPtr->readyMasks.writable) ) ) { + if (FD_ISSET(filePtr->fd, &(tsdPtr->readyMasks.writable))) { mask |= TCL_WRITABLE; } - if ( FD_ISSET( filePtr->fd, &(tsdPtr->readyMasks.exceptional) ) ) { + if (FD_ISSET(filePtr->fd, &(tsdPtr->readyMasks.exceptional))) { mask |= TCL_EXCEPTION; } @@ -871,8 +899,7 @@ TkMacOSXWaitForEvent(timePtr) */ if (filePtr->readyMask == 0) { - fileEvPtr = (FileHandlerEvent *) ckalloc( - sizeof(FileHandlerEvent)); + fileEvPtr = (FileHandlerEvent *) ckalloc(sizeof(FileHandlerEvent)); fileEvPtr->header.proc = FileHandlerEventProc; fileEvPtr->fd = filePtr->fd; Tcl_QueueEvent((Tcl_Event *) fileEvPtr, TCL_QUEUE_TAIL); @@ -885,9 +912,9 @@ TkMacOSXWaitForEvent(timePtr) * Also queue the Mac Events found... */ if (tsdPtr->isMainLoop) { - TkMacOSXCountAndProcessMacEvents(); + TkMacOSXCountAndProcessMacEvents(); } - + return 0; } @@ -966,10 +993,9 @@ NotifierThreadProc(clientData) */ while (1) { - - FD_ZERO( &readableMask ); - FD_ZERO( &writableMask ); - FD_ZERO( &exceptionalMask ); + FD_ZERO(&readableMask); + FD_ZERO(&writableMask); + FD_ZERO(&exceptionalMask); /* * Compute the logical OR of the select masks from all the @@ -978,19 +1004,19 @@ NotifierThreadProc(clientData) Tcl_MutexLock(¬ifierMutex); timePtr = NULL; - for (tsdPtr = waitingListPtr; tsdPtr; tsdPtr = tsdPtr->nextPtr) { - for ( i = tsdPtr->numFdBits-1; i >= 0; --i ) { - if ( FD_ISSET( i, &(tsdPtr->checkMasks.readable) ) ) { - FD_SET( i, &readableMask ); + for (tsdPtr = waitingListPtr; tsdPtr; tsdPtr = tsdPtr->nextPtr) { + for (i = tsdPtr->numFdBits-1; i >= 0; --i) { + if (FD_ISSET(i, &(tsdPtr->checkMasks.readable))) { + FD_SET(i, &readableMask); } - if ( FD_ISSET( i, &(tsdPtr->checkMasks.writable) ) ) { - FD_SET( i, &writableMask ); + if (FD_ISSET(i, &(tsdPtr->checkMasks.writable))) { + FD_SET(i, &writableMask); } - if ( FD_ISSET( i, &(tsdPtr->checkMasks.exceptional) ) ) { - FD_SET( i, &exceptionalMask ); + if (FD_ISSET(i, &(tsdPtr->checkMasks.exceptional))) { + FD_SET(i, &exceptionalMask); } } - if ( tsdPtr->numFdBits > numFdBits ) { + if (tsdPtr->numFdBits > numFdBits) { numFdBits = tsdPtr->numFdBits; } if (tsdPtr->pollState & POLL_WANT) { @@ -1009,48 +1035,48 @@ NotifierThreadProc(clientData) * Set up the select mask to include the receive pipe. */ - if ( receivePipe >= numFdBits ) { + if (receivePipe >= numFdBits) { numFdBits = receivePipe + 1; } - FD_SET( receivePipe, &readableMask ); + FD_SET(receivePipe, &readableMask); - if ( select( numFdBits, &readableMask, &writableMask, - &exceptionalMask, timePtr) == -1 ) { + if (select(numFdBits, &readableMask, &writableMask, &exceptionalMask, + timePtr) == -1) { /* * Try again immediately on an error. */ continue; - } + } /* * Alert any threads that are waiting on a ready file descriptor. */ Tcl_MutexLock(¬ifierMutex); - for (tsdPtr = waitingListPtr; tsdPtr; tsdPtr = tsdPtr->nextPtr) { + for (tsdPtr = waitingListPtr; tsdPtr; tsdPtr = tsdPtr->nextPtr) { found = 0; - for ( i = tsdPtr->numFdBits-1; i >= 0; --i ) { - if ( FD_ISSET( i, &(tsdPtr->checkMasks.readable) ) - && FD_ISSET( i, &readableMask ) ) { - FD_SET( i, &(tsdPtr->readyMasks.readable) ); + for (i = tsdPtr->numFdBits-1; i >= 0; --i) { + if (FD_ISSET(i, &(tsdPtr->checkMasks.readable)) + && FD_ISSET(i, &readableMask)) { + FD_SET(i, &(tsdPtr->readyMasks.readable)); found = 1; } - if ( FD_ISSET( i, &(tsdPtr->checkMasks.writable) ) - && FD_ISSET( i, &writableMask ) ) { - FD_SET( i, &(tsdPtr->readyMasks.writable) ); + if (FD_ISSET(i, &(tsdPtr->checkMasks.writable)) + && FD_ISSET(i, &writableMask)) { + FD_SET(i, &(tsdPtr->readyMasks.writable)); found = 1; } - if ( FD_ISSET( i, &(tsdPtr->checkMasks.exceptional) ) - && FD_ISSET( i, &exceptionalMask ) ) { - FD_SET( i, &(tsdPtr->readyMasks.exceptional) ); + if (FD_ISSET(i, &(tsdPtr->checkMasks.exceptional)) + && FD_ISSET(i, &exceptionalMask)) { + FD_SET(i, &(tsdPtr->readyMasks.exceptional)); found = 1; } } - - if (found || (tsdPtr->pollState & POLL_DONE)) { - tsdPtr->eventReady = 1; + + if (found || (tsdPtr->pollState & POLL_DONE)) { + tsdPtr->eventReady = 1; if (tsdPtr->onList) { /* * Remove the ThreadSpecificData structure of this @@ -1058,7 +1084,7 @@ NotifierThreadProc(clientData) * continuously spining on select until the other * threads runs and services the file event. */ - + if (tsdPtr->prevPtr) { tsdPtr->prevPtr->nextPtr = tsdPtr->nextPtr; } else { @@ -1071,30 +1097,18 @@ NotifierThreadProc(clientData) tsdPtr->onList = 0; tsdPtr->pollState = 0; } - if (tsdPtr->isMainLoop) { - OSErr err; - - /* We need to wake up the main loop, and let it have the event. */ - EventRef fakeEvent = TkMacOSXCreateFakeEvent(); - EventQueueRef mainEventQueue = GetMainEventQueue(); - - err = PostEventToQueue(mainEventQueue, fakeEvent, - kEventPriorityHigh); - ReleaseEvent(fakeEvent); - } else { - Tcl_ConditionNotify(&tsdPtr->waitCV); - } - } - } + AlertNotifier(tsdPtr); + } + } Tcl_MutexUnlock(¬ifierMutex); - + /* * Consume the next byte from the notifier pipe if the pipe was * readable. Note that there may be multiple bytes pending, but * to avoid a race condition we only read one at a time. */ - if ( FD_ISSET( receivePipe, &readableMask ) ) { + if (FD_ISSET(receivePipe, &readableMask)) { i = read(receivePipe, buf, 1); if ((i == 0) || ((i == 1) && (buf[0] == 'q'))) { @@ -1120,23 +1134,25 @@ NotifierThreadProc(clientData) Tcl_ConditionNotify(¬ifierCV); Tcl_MutexUnlock(¬ifierMutex); - Tcl_ExitThread (0); + Tcl_ExitThread(0); } - + EventRef -TkMacOSXCreateFakeEvent () +TkMacOSXCreateFakeEvent() { - EventKind eKind; - EventClass eClass; - EventTime eTime; - EventRef eventRef; + EventKind eKind; + EventClass eClass; + EventTime eTime; + EventRef eventRef; EventAttributes flags; + eClass = kEventClassWish; eKind = 0xffff; eTime = GetLastUserEventTime() + 0.001; flags = kEventAttributeUserEvent; if (CreateEvent(NULL,eClass,eKind,eTime,flags,&eventRef) != noErr) { - fprintf(stderr,"CreateEvent failed\n"); + /* DKF: Printing to stderr? Leaked debug code here? */ + fprintf(stderr, "CreateEvent failed\n"); return NULL; } return eventRef; -- cgit v0.12