Index: macosx/tkMacOSXInit.c =================================================================== RCS file: /cvsroot/tktoolkit/tk/macosx/tkMacOSXInit.c,v retrieving revision 1.8 diff -u -p -r1.8 tkMacOSXInit.c --- macosx/tkMacOSXInit.c 9 Mar 2005 19:40:52 -0000 1.8 +++ macosx/tkMacOSXInit.c 17 Apr 2005 04:37:39 -0000 @@ -126,6 +126,18 @@ TkpInit(interp) char *encodingStr = NULL; int i; + int threaded; + Tcl_Obj *threadedObj; + + threadedObj = Tcl_GetVar2Ex(interp, "::tcl_platform", "threaded", + TCL_GLOBAL_ONLY); + if (!threadedObj || + Tcl_GetBooleanFromObj(interp, threadedObj, &threaded) != TCL_OK || + !threaded) { + Tcl_AppendResult(interp, "TkAqua requires threaded Tcl!", NULL); + return TCL_ERROR; + } + tkMacOSXInitialized = true; Tk_MacOSXSetupTkNotifier(); Index: macosx/tkMacOSXNotify.c =================================================================== RCS file: /cvsroot/tktoolkit/tk/macosx/tkMacOSXNotify.c,v retrieving revision 1.8 diff -u -p -r1.8 tkMacOSXNotify.c --- macosx/tkMacOSXNotify.c 24 Feb 2005 00:41:04 -0000 1.8 +++ macosx/tkMacOSXNotify.c 17 Apr 2005 04:37:39 -0000 @@ -21,6 +21,10 @@ #include +#ifndef TCL_THREADS +#error Mac OS X notifier requires tcl threads! +#endif + extern TclStubs tclStubs; /* @@ -57,6 +61,18 @@ typedef struct FileHandlerEvent { } FileHandlerEvent; /* + * + * The following structure contains a set of select() masks to track + * readable, writable, and exceptional conditions. + */ + +typedef struct SelectMasks { + fd_set readable; + fd_set writable; + fd_set exceptional; +} SelectMasks; + +/* * The following static structure contains the state information for the * select based implementation of the Tcl notifier. One of these structures * is created for each thread that is using the notifier. @@ -65,13 +81,12 @@ typedef struct FileHandlerEvent { typedef struct ThreadSpecificData { FileHandler *firstFileHandlerPtr; /* Pointer to head of file handler list. */ - fd_mask checkMasks[3*MASK_SIZE]; - /* This array is used to build up the masks + + 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 * Tcl_CreateFileHandler. */ - fd_mask readyMasks[3*MASK_SIZE]; - /* This array reflects the readable/writable + SelectMasks readyMasks; /* This array reflects the readable/writable * conditions that were found to exist by the * last call to select. */ int numFdBits; /* Number of valid bits in checkMasks @@ -79,7 +94,6 @@ typedef struct ThreadSpecificData { * Tcl_WatchFile has been called). */ int isMainLoop; /* Is this the main Carbon Loop (in which case * we will call RNE in the actual wait... */ -#ifdef TCL_THREADS 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 @@ -97,12 +111,10 @@ typedef struct ThreadSpecificData { int eventReady; /* True if an event is ready to be processed. * Used as condition flag together with * waitCV above. */ -#endif } ThreadSpecificData; static Tcl_ThreadDataKey dataKey; -#ifdef TCL_THREADS /* * The following static indicates the number of threads that have * initialized notifiers. @@ -170,15 +182,11 @@ static Tcl_Condition notifierCV; */ static Tcl_ThreadId notifierThread; -#endif - /* * Static routines defined in this file. */ -#ifdef TCL_THREADS static void NotifierThreadProc _ANSI_ARGS_((ClientData clientData)); -#endif static int FileHandlerEventProc _ANSI_ARGS_((Tcl_Event *evPtr, int flags)); @@ -194,7 +202,7 @@ EventRef TkMacOSXCreateFakeEvent (); /* *---------------------------------------------------------------------- * - * TkMacOSXSetupTkNotifier -- + * Tk_MacOSXSetupTkNotifier -- * * Replaces the Tcl notifier (from tclUnixNotfy.c) with * the Mac notifier that melds the Unix select based notifer @@ -273,7 +281,6 @@ TkMacOSXInitNotifier() { ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); -#ifdef TCL_THREADS tsdPtr->eventReady = 0; /* @@ -304,7 +311,6 @@ TkMacOSXInitNotifier() } Tcl_MutexUnlock(¬ifierMutex); -#endif return (ClientData) tsdPtr; } @@ -330,7 +336,6 @@ void TkMacOSXFinalizeNotifier(clientData) ClientData clientData; /* Not used. */ { -#ifdef TCL_THREADS ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); Tcl_MutexLock(¬ifierMutex); @@ -369,7 +374,6 @@ TkMacOSXFinalizeNotifier(clientData) Tcl_ConditionFinalize(&(tsdPtr->waitCV)); Tcl_MutexUnlock(¬ifierMutex); -#endif } /* @@ -397,13 +401,23 @@ void TkMacOSXAlertNotifier(clientData) ClientData clientData; { -#ifdef TCL_THREADS ThreadSpecificData *tsdPtr = (ThreadSpecificData *) clientData; Tcl_MutexLock(¬ifierMutex); tsdPtr->eventReady = 1; - Tcl_ConditionNotify(&tsdPtr->waitCV); + 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); + } Tcl_MutexUnlock(¬ifierMutex); -#endif } /* @@ -488,7 +502,6 @@ TkMacOSXCreateFileHandler(fd, mask, proc { ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); FileHandler *filePtr; - int index, bit; for (filePtr = tsdPtr->firstFileHandlerPtr; filePtr != NULL; filePtr = filePtr->nextPtr) { @@ -511,22 +524,20 @@ TkMacOSXCreateFileHandler(fd, mask, proc * Update the check masks for this file. */ - index = fd/(NBBY*sizeof(fd_mask)); - bit = 1 << (fd%(NBBY*sizeof(fd_mask))); - if (mask & TCL_READABLE) { - tsdPtr->checkMasks[index] |= bit; + if ( mask & TCL_READABLE ) { + FD_SET( fd, &(tsdPtr->checkMasks.readable) ); } else { - tsdPtr->checkMasks[index] &= ~bit; - } - if (mask & TCL_WRITABLE) { - (tsdPtr->checkMasks+MASK_SIZE)[index] |= bit; + FD_CLR( fd, &(tsdPtr->checkMasks.readable) ); + } + if ( mask & TCL_WRITABLE ) { + FD_SET( fd, &(tsdPtr->checkMasks.writable) ); } else { - (tsdPtr->checkMasks+MASK_SIZE)[index] &= ~bit; + FD_CLR( fd, &(tsdPtr->checkMasks.writable) ); } - if (mask & TCL_EXCEPTION) { - (tsdPtr->checkMasks+2*(MASK_SIZE))[index] |= bit; + if ( mask & TCL_EXCEPTION ) { + FD_SET( fd, &(tsdPtr->checkMasks.exceptional) ); } else { - (tsdPtr->checkMasks+2*(MASK_SIZE))[index] &= ~bit; + FD_CLR( fd, &(tsdPtr->checkMasks.exceptional) ); } if (tsdPtr->numFdBits <= fd) { tsdPtr->numFdBits = fd+1; @@ -555,8 +566,7 @@ TkMacOSXDeleteFileHandler(fd) int fd; /* Stream id for which to remove callback procedure. */ { FileHandler *filePtr, *prevPtr; - int index, bit, i; - unsigned long flags; + int i; ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); /* @@ -577,17 +587,14 @@ TkMacOSXDeleteFileHandler(fd) * Update the check masks for this file. */ - index = fd/(NBBY*sizeof(fd_mask)); - bit = 1 << (fd%(NBBY*sizeof(fd_mask))); - if (filePtr->mask & TCL_READABLE) { - tsdPtr->checkMasks[index] &= ~bit; + FD_CLR( fd, &(tsdPtr->checkMasks.readable) ); } if (filePtr->mask & TCL_WRITABLE) { - (tsdPtr->checkMasks+MASK_SIZE)[index] &= ~bit; + FD_CLR( fd, &(tsdPtr->checkMasks.writable) ); } if (filePtr->mask & TCL_EXCEPTION) { - (tsdPtr->checkMasks+2*(MASK_SIZE))[index] &= ~bit; + FD_CLR( fd, &(tsdPtr->checkMasks.exceptional) ); } /* @@ -595,17 +602,12 @@ TkMacOSXDeleteFileHandler(fd) */ if (fd+1 == tsdPtr->numFdBits) { - for (tsdPtr->numFdBits = 0; index >= 0; index--) { - flags = tsdPtr->checkMasks[index] - | (tsdPtr->checkMasks+MASK_SIZE)[index] - | (tsdPtr->checkMasks+2*(MASK_SIZE))[index]; - if (flags) { - for (i = (NBBY*sizeof(fd_mask)); i > 0; i--) { - if (flags & (((unsigned long)1) << (i-1))) { - break; - } - } - tsdPtr->numFdBits = index * (NBBY*sizeof(fd_mask)) + i; + 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 ) ) ) { + tsdPtr->numFdBits = i+1; break; } } @@ -696,31 +698,6 @@ FileHandlerEventProc(evPtr, flags) return 1; } -void -DoActualWait(timePtr) - Tcl_Time *timePtr; /* Maximum block time, or NULL. */ -{ - ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); - OSErr err; - - if (!tsdPtr->isMainLoop) { - Tcl_ConditionWait(&tsdPtr->waitCV, ¬ifierMutex, timePtr); - } else { - EventRef eventRef; - EventTime waitTime; - Tcl_MutexUnlock(¬ifierMutex); - - if (timePtr == NULL) { - waitTime = kEventDurationForever; - } else { - waitTime = timePtr->sec * kEventDurationSecond - + timePtr->usec * kEventDurationMicrosecond; - } - err = ReceiveNextEvent(0, NULL, waitTime, false, &eventRef); - Tcl_MutexLock(¬ifierMutex); - } -} - /* *---------------------------------------------------------------------- * @@ -746,14 +723,10 @@ TkMacOSXWaitForEvent(timePtr) { FileHandler *filePtr; FileHandlerEvent *fileEvPtr; - struct timeval timeout, *timeoutPtr; - int bit, index, mask; -#ifdef TCL_THREADS + int mask; + Tcl_Time myTime; int waitForFiles; -#else - int numFound; -#endif - + Tcl_Time *myTimePtr; ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); /* @@ -763,26 +736,26 @@ TkMacOSXWaitForEvent(timePtr) */ if (timePtr) { - timeout.tv_sec = timePtr->sec; - timeout.tv_usec = timePtr->usec; - timeoutPtr = &timeout; -#ifndef TCL_THREADS - } else if (tsdPtr->numFdBits == 0) { - /* - * If there are no threads, no timeout, and no fds registered, - * then there are no events possible and we must avoid deadlock. - * Note that this is not entirely correct because there might - * be a signal that could interrupt the select call, but we - * don't handle that case if we aren't using threads. - */ + /* 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.usec = timePtr->usec; + + if (myTime.sec != 0 || myTime.usec != 0) { + Tcl_ScaleTimeProc* tclScaleTimeProcPtr; + ClientData tclTimeClientData; + Tcl_QueryTimeProc(NULL, &tclScaleTimeProcPtr, &tclTimeClientData); + + (*tclScaleTimeProcPtr) (&myTime, tclTimeClientData); + } - return -1; -#endif + myTimePtr = &myTime; } else { - timeoutPtr = NULL; + myTimePtr = NULL; } -#ifdef TCL_THREADS /* * Place this thread on the list of interested threads, signal the * notifier thread, and wait for a response or a timeout. @@ -791,7 +764,7 @@ TkMacOSXWaitForEvent(timePtr) Tcl_MutexLock(¬ifierMutex); waitForFiles = (tsdPtr->numFdBits > 0); - if (timePtr != NULL && timePtr->sec == 0 && timePtr->usec == 0) { + if (myTimePtr != NULL && myTimePtr->sec == 0 && myTimePtr->usec == 0) { /* * Cannot emulate a polling select with a polling condition variable. * Instead, pretend to wait for files and tell the notifier @@ -802,7 +775,7 @@ TkMacOSXWaitForEvent(timePtr) waitForFiles = 1; tsdPtr->pollState = POLL_WANT; - timePtr = NULL; + myTimePtr = NULL; } else { tsdPtr->pollState = 0; } @@ -826,10 +799,28 @@ TkMacOSXWaitForEvent(timePtr) write(triggerPipe, "", 1); } - memset((VOID *) tsdPtr->readyMasks, 0, 3*MASK_SIZE*sizeof(fd_mask)); + FD_ZERO( &(tsdPtr->readyMasks.readable) ); + FD_ZERO( &(tsdPtr->readyMasks.writable) ); + FD_ZERO( &(tsdPtr->readyMasks.exceptional) ); if (!tsdPtr->eventReady) { - DoActualWait(timePtr); + 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; @@ -855,41 +846,21 @@ TkMacOSXWaitForEvent(timePtr) } -#else - memcpy((VOID *) tsdPtr->readyMasks, (VOID *) tsdPtr->checkMasks, - 3*MASK_SIZE*sizeof(fd_mask)); - numFound = select(tsdPtr->numFdBits, - (SELECT_MASK *) &tsdPtr->readyMasks[0], - (SELECT_MASK *) &tsdPtr->readyMasks[MASK_SIZE], - (SELECT_MASK *) &tsdPtr->readyMasks[2*MASK_SIZE], timeoutPtr); - - /* - * Some systems don't clear the masks after an error, so - * we have to do it here. - */ - - if (numFound == -1) { - memset((VOID *) tsdPtr->readyMasks, 0, 3*MASK_SIZE*sizeof(fd_mask)); - } -#endif - /* * Queue all detected file events before returning. */ for (filePtr = tsdPtr->firstFileHandlerPtr; (filePtr != NULL); filePtr = filePtr->nextPtr) { - index = filePtr->fd / (NBBY*sizeof(fd_mask)); - bit = 1 << (filePtr->fd % (NBBY*sizeof(fd_mask))); - mask = 0; - if (tsdPtr->readyMasks[index] & bit) { + mask = 0; + if ( FD_ISSET( filePtr->fd, &(tsdPtr->readyMasks.readable) ) ) { mask |= TCL_READABLE; } - if ((tsdPtr->readyMasks+MASK_SIZE)[index] & bit) { + if ( FD_ISSET( filePtr->fd, &(tsdPtr->readyMasks.writable) ) ) { mask |= TCL_WRITABLE; } - if ((tsdPtr->readyMasks+2*(MASK_SIZE))[index] & bit) { + if ( FD_ISSET( filePtr->fd, &(tsdPtr->readyMasks.exceptional) ) ) { mask |= TCL_EXCEPTION; } @@ -911,15 +882,11 @@ TkMacOSXWaitForEvent(timePtr) } filePtr->readyMask = mask; } - + Tcl_MutexUnlock(¬ifierMutex); + /* * Also queue the Mac Events found... */ - -#ifdef TCL_THREADS - Tcl_MutexUnlock(¬ifierMutex); -#endif - if (tsdPtr->isMainLoop) { TkMacOSXCountAndProcessMacEvents(); } @@ -927,7 +894,6 @@ TkMacOSXWaitForEvent(timePtr) return 0; } -#ifdef TCL_THREADS /* *---------------------------------------------------------------------- * @@ -958,12 +924,13 @@ NotifierThreadProc(clientData) ClientData clientData; /* Not used. */ { ThreadSpecificData *tsdPtr; - fd_mask masks[3*MASK_SIZE]; - long *maskPtr = (long *)masks; /* masks[] cast to type long[] */ + fd_set readableMask; + fd_set writableMask; + fd_set exceptionalMask; int fds[2]; - int i, status, index, bit, numFdBits, found, receivePipe, word; + int i, status, numFdBits = 0, receivePipe; + long found; struct timeval poll = {0., 0.}, *timePtr; - int maskSize = 3 * ((MASK_SIZE) / sizeof(long)) * sizeof(fd_mask); char buf[2]; if (pipe(fds) != 0) { @@ -972,7 +939,6 @@ NotifierThreadProc(clientData) receivePipe = fds[0]; -#ifndef USE_FIONBIO status = fcntl(receivePipe, F_GETFL); status |= O_NONBLOCK; if (fcntl(receivePipe, F_SETFL, status) < 0) { @@ -983,14 +949,6 @@ NotifierThreadProc(clientData) if (fcntl(fds[1], F_SETFL, status) < 0) { Tcl_Panic("NotifierThreadProc: could not make trigger pipe non blocking."); } -#else - if (ioctl(receivePipe, (int) FIONBIO, &status) < 0) { - Tcl_Panic("NotifierThreadProc: could not make receive pipe non blocking."); - } - if (ioctl(fds[1], (int) FIONBIO, &status) < 0) { - Tcl_Panic("NotifierThreadProc: could not make trigger pipe non blocking."); - } -#endif /* * Install the write end of the pipe into the global variable. @@ -1011,29 +969,33 @@ NotifierThreadProc(clientData) */ while (1) { - /* - * Set up the select mask to include the receive pipe. - */ - memset((VOID *)masks, 0, 3*MASK_SIZE*sizeof(fd_mask)); - numFdBits = receivePipe + 1; - index = receivePipe / (NBBY*sizeof(fd_mask)); - bit = 1 << (receivePipe % (NBBY*sizeof(fd_mask))); - masks[index] |= bit; + FD_ZERO( &readableMask ); + FD_ZERO( &writableMask ); + FD_ZERO( &exceptionalMask ); /* - * Add in the check masks from all of the waiting notifiers. + * Compute the logical OR of the select masks from all the + * waiting notifiers. */ - + Tcl_MutexLock(¬ifierMutex); timePtr = NULL; for (tsdPtr = waitingListPtr; tsdPtr; tsdPtr = tsdPtr->nextPtr) { - for (i = 0; i < maskSize; i++) { - maskPtr[i] |= ((long*)tsdPtr->checkMasks)[i]; - } - if (tsdPtr->numFdBits > numFdBits) { - numFdBits = tsdPtr->numFdBits; - } + 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.exceptional) ) ) { + FD_SET( i, &exceptionalMask ); + } + } + if ( tsdPtr->numFdBits > numFdBits ) { + numFdBits = tsdPtr->numFdBits; + } if (tsdPtr->pollState & POLL_WANT) { /* * Here we make sure we go through select() with the same @@ -1043,14 +1005,20 @@ NotifierThreadProc(clientData) tsdPtr->pollState |= POLL_DONE; timePtr = &poll; } - } + } Tcl_MutexUnlock(¬ifierMutex); - maskSize = 3 * ((MASK_SIZE) / sizeof(long)) * sizeof(fd_mask); + /* + * Set up the select mask to include the receive pipe. + */ + + if ( receivePipe >= numFdBits ) { + numFdBits = receivePipe + 1; + } + FD_SET( receivePipe, &readableMask ); - if (select(numFdBits, (SELECT_MASK *) &masks[0], - (SELECT_MASK *) &masks[MASK_SIZE], - (SELECT_MASK *) &masks[2*MASK_SIZE], timePtr) == -1) { + if ( select( numFdBits, &readableMask, &writableMask, + &exceptionalMask, timePtr) == -1 ) { /* * Try again immediately on an error. */ @@ -1066,33 +1034,46 @@ NotifierThreadProc(clientData) for (tsdPtr = waitingListPtr; tsdPtr; tsdPtr = tsdPtr->nextPtr) { found = 0; - for (i = 0; i < maskSize; i++) { - word = maskPtr[i] & ((long*)tsdPtr->checkMasks)[i]; - found |= word; - (((long*)(tsdPtr->readyMasks))[i]) = word; + 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) ); + found = 1; + } + 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)) { - if (tsdPtr->onList) { - /* - * Remove the ThreadSpecificData structure of this - * thread from the waiting list. This prevents us from - * continuously spining on select until the other - * threads runs and services the file event. - */ - - 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; - tsdPtr->pollState = 0; - } tsdPtr->eventReady = 1; + if (tsdPtr->onList) { + /* + * Remove the ThreadSpecificData structure of this + * thread from the waiting list. This prevents us from + * continuously spining on select until the other + * threads runs and services the file event. + */ + + 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; + tsdPtr->pollState = 0; + } if (tsdPtr->isMainLoop) { OSErr err; @@ -1116,8 +1097,9 @@ NotifierThreadProc(clientData) * to avoid a race condition we only read one at a time. */ - if (masks[index] & bit) { + if ( FD_ISSET( receivePipe, &readableMask ) ) { i = read(receivePipe, buf, 1); + if ((i == 0) || ((i == 1) && (buf[0] == 'q'))) { /* * Someone closed the write end of the pipe or sent us a @@ -1140,8 +1122,9 @@ NotifierThreadProc(clientData) triggerPipe = -1; Tcl_ConditionNotify(¬ifierCV); Tcl_MutexUnlock(¬ifierMutex); + + Tcl_ExitThread (0); } -#endif EventRef TkMacOSXCreateFakeEvent () Index: macosx/Wish.pbproj/project.pbxproj =================================================================== RCS file: /cvsroot/tktoolkit/tk/macosx/Wish.pbproj/project.pbxproj,v retrieving revision 1.38 diff -u -p -r1.38 project.pbxproj --- macosx/Wish.pbproj/project.pbxproj 9 Apr 2005 11:19:00 -0000 1.38 +++ macosx/Wish.pbproj/project.pbxproj 17 Apr 2005 04:37:39 -0000 @@ -126,12 +126,6 @@ settings = { }; }; - F51D903E0181474301DC9062 = { - fileRef = F5875C7B016FEF1D01DC9062; - isa = PBXBuildFile; - settings = { - }; - }; F51D903F018149BD01DC9062 = { buildActionMask = 2147483647; dstPath = "Versions/$(FRAMEWORK_VERSION)/Headers/X11"; @@ -1906,6 +1900,7 @@ F53755DF016C38D201DC9062 = { buildPhases = ( F5877FB7031F97ED016F146B, + F92CCC75080CEBA800E72D64, F53755E0016C38D201DC9062, F53755E1016C38D301DC9062, F53755E2016C38D301DC9062, @@ -1929,10 +1924,10 @@ GLOBAL_CFLAGS = "`source \"${TCL_FRAMEWORK_DIR}/Tcl.framework/tclConfig.sh\"; echo $${}{TCL_EXTRA_CFLAGS} $${}{TCL_DEFS} | sed -e 's|\\\\\\\\\\\\\\\"|\\\"|g' -e 's|\\\\\\\\\\\\ |_|g'`"; HEADER_SEARCH_PATHS = "\"$(TCL_FRAMEWORK_DIR)/Tcl.framework/Headers\" \"$(TCL_FRAMEWORK_DIR)/Tcl.framework/PrivateHeaders\" . ../bitmaps ../generic ../xlib"; INSTALL_PATH = "${DYLIB_INSTALL_PATH}"; - LIBRARY_SEARCH_PATHS = ""; + LIBRARY_SEARCH_PATHS = "\"$(TCL_FRAMEWORK_DIR)/Tcl.framework\""; OPTIMIZATION_CFLAGS = "-O0"; - OTHER_CFLAGS = "-DMAC_OSX_TK -DTCL_WIDE_INT_TYPE=\"long long\""; - OTHER_LDFLAGS = "-seg1addr 0xb000000"; + OTHER_CFLAGS = "-DMAC_OSX_TK -DUSE_TCL_STUBS -DTCL_WIDE_INT_TYPE=\"long long\""; + OTHER_LDFLAGS = "-ltclstub${FRAMEWORK_VERSION} -seg1addr 0xb000000 -Wl,-search_paths_first -unexported_symbols_list \"${TEMP_DIR}/tclstub.exp\""; OTHER_LIBTOOL_FLAGS = ""; OTHER_REZFLAGS = "-i \"$(TCL_FRAMEWORK_DIR)/Tcl.framework/Headers\" -i \"../generic\""; PRECOMPILE_PREFIX_HEADER = YES; @@ -2172,7 +2167,6 @@ MacOS X Port by Jim Ingham <jingham@a F53755E3016C38D301DC9062 = { buildActionMask = 2147483647; files = ( - F51D903E0181474301DC9062, F537567E016C3ADB01DC9062, F50D96130196176E01DC9062, ); @@ -4284,6 +4278,19 @@ MacOS X Port by Jim Ingham <jingham@a //F92 //F93 //F94 + F92CCC75080CEBA800E72D64 = { + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + isa = PBXShellScriptBuildPhase; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "# extract global symbols in libtclstub so that we can unexport them from Tk.framework\nnm -gjp \"${TCL_FRAMEWORK_DIR}/Tcl.framework/libtclstub${FRAMEWORK_VERSION}.a\" | tail +3 > \"${TEMP_DIR}/tclstub.exp\""; + }; F92ED9910403D0F0006F146B = { fileEncoding = 5; isa = PBXFileReference;