diff options
Diffstat (limited to 'unix/tclUnixNotfy.c')
-rw-r--r-- | unix/tclUnixNotfy.c | 147 |
1 files changed, 145 insertions, 2 deletions
diff --git a/unix/tclUnixNotfy.c b/unix/tclUnixNotfy.c index ebbbb78..c1bc430 100644 --- a/unix/tclUnixNotfy.c +++ b/unix/tclUnixNotfy.c @@ -91,9 +91,16 @@ typedef struct ThreadSpecificData { * from these pointers. You must hold the * notifierMutex lock before accessing these * fields. */ +#ifdef __CYGWIN__ + void *event; /* Any other thread alerts a notifier + * that an event is ready to be processed + * by sending this event. */ + void *hwnd; /* Messaging window. */ +#else /* !__CYGWIN__ */ Tcl_Condition waitCV; /* Any other thread alerts a notifier that an * event is ready to be processed by signaling * this condition variable. */ +#endif /* __CYGWIN__ */ int eventReady; /* True if an event is ready to be processed. * Used as condition flag together with waitCV * above. */ @@ -197,6 +204,48 @@ static int FileHandlerEventProc(Tcl_Event *evPtr, int flags); *---------------------------------------------------------------------- */ +#if defined(TCL_THREADS) && defined(__CYGWIN__) + +typedef struct { + void *hwnd; + unsigned int *message; + int wParam; + int lParam; + int time; + int x; + int y; +} MSG; + +typedef struct { + unsigned int style; + void *lpfnWndProc; + int cbClsExtra; + int cbWndExtra; + void *hInstance; + void *hIcon; + void *hCursor; + void *hbrBackground; + void *lpszMenuName; + void *lpszClassName; +} WNDCLASS; + +extern unsigned char __stdcall PeekMessageW(MSG *, void *, int, int, int); +extern unsigned char __stdcall GetMessageW(MSG *, void *, int, int); +extern unsigned char __stdcall TranslateMessage(const MSG *); +extern int __stdcall DispatchMessageW(const MSG *); +extern void __stdcall PostQuitMessage(int); +extern void * __stdcall CreateWindowExW(void *, void *, void *, DWORD, int, int, int, int, void *, void *, void *, void *); +extern unsigned char __stdcall DestroyWindow(void *); +extern unsigned char __stdcall PostMessageW(void *, unsigned int, void *, void *); +extern void *__stdcall RegisterClassW(const WNDCLASS *); +extern DWORD __stdcall DefWindowProcW(void *, int, void *, void *); +extern void *__stdcall CreateEventW(void *, unsigned char, unsigned char, void *); +extern void __stdcall CloseHandle(void *); +extern void __stdcall MsgWaitForMultipleObjects(DWORD, void *, unsigned char, DWORD, DWORD); +extern unsigned char __stdcall ResetEvent(void *); + +#endif + ClientData Tcl_InitNotifier(void) { @@ -311,7 +360,11 @@ Tcl_FinalizeNotifier( * Clean up any synchronization objects in the thread local storage. */ - Tcl_ConditionFinalize(&tsdPtr->waitCV); +#ifdef __CYGWIN__ + CloseHandle(tsdPtr->event); +#else /* __CYGWIN__ */ + Tcl_ConditionFinalize(&(tsdPtr->waitCV)); +#endif /* __CYGWIN__ */ Tcl_MutexUnlock(¬ifierMutex); #endif /* TCL_THREADS */ @@ -350,7 +403,11 @@ Tcl_AlertNotifier( Tcl_MutexLock(¬ifierMutex); tsdPtr->eventReady = 1; +#ifdef __CYGWIN__ + PostMessageW(tsdPtr->hwnd, 1024, 0, 0); +#else Tcl_ConditionNotify(&tsdPtr->waitCV); +#endif Tcl_MutexUnlock(¬ifierMutex); #endif /* TCL_THREADS */ } @@ -656,6 +713,31 @@ FileHandlerEventProc( return 1; } +#if defined(TCL_THREADS) && defined(__CYGWIN__) + +static DWORD __stdcall +NotifierProc( + void *hwnd, + unsigned int message, + void *wParam, + void *lParam) +{ + ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); + + if (message != 1024) { + return DefWindowProcW(hwnd, message, wParam, lParam); + } + + /* + * Process all of the runnable events. + */ + + tsdPtr->eventReady = 1; + Tcl_ServiceAll(); + return 0; +} +#endif /* __CYGWIN__ */ + /* *---------------------------------------------------------------------- * @@ -686,6 +768,9 @@ Tcl_WaitForEvent( Tcl_Time vTime; #ifdef TCL_THREADS int waitForFiles; +# ifdef __CYGWIN__ + MSG msg; +# endif #else /* * Impl. notes: timeout & timeoutPtr are used if, and only if threads @@ -741,6 +826,30 @@ Tcl_WaitForEvent( * notifier thread, and wait for a response or a timeout. */ +#ifdef __CYGWIN__ + if (!tsdPtr->hwnd) { + WNDCLASS class; + + class.style = 0; + class.cbClsExtra = 0; + class.cbWndExtra = 0; + class.hInstance = TclWinGetTclInstance(); + class.hbrBackground = NULL; + class.lpszMenuName = NULL; + class.lpszClassName = L"TclNotifier"; + class.lpfnWndProc = NotifierProc; + class.hIcon = NULL; + class.hCursor = NULL; + + RegisterClassW(&class); + tsdPtr->hwnd = CreateWindowExW(NULL, class.lpszClassName, class.lpszClassName, + 0, 0, 0, 0, 0, NULL, NULL, TclWinGetTclInstance(), NULL); + tsdPtr->event = CreateEventW(NULL, 1 /* manual */, + 0 /* !signaled */, NULL); + } + +#endif + Tcl_MutexLock(¬ifierMutex); if (timePtr != NULL && timePtr->sec == 0 && (timePtr->usec == 0 @@ -797,10 +906,40 @@ Tcl_WaitForEvent( FD_ZERO(&tsdPtr->readyMasks.exception); if (!tsdPtr->eventReady) { +#ifdef __CYGWIN__ + if (!PeekMessageW(&msg, NULL, 0, 0, 0)) { + DWORD timeout; + if (timePtr) { + timeout = timePtr->sec * 1000 + timePtr->usec / 1000; + } else { + timeout = 0xFFFFFFFF; + } + Tcl_MutexUnlock(¬ifierMutex); + MsgWaitForMultipleObjects(1, &tsdPtr->event, 0, timeout, 1279); + Tcl_MutexLock(¬ifierMutex); + } +#else Tcl_ConditionWait(&tsdPtr->waitCV, ¬ifierMutex, timePtr); +#endif } tsdPtr->eventReady = 0; +#ifdef __CYGWIN__ + while (PeekMessageW(&msg, NULL, 0, 0, 0)) { + /* + * Retrieve and dispatch the message. + */ + DWORD result = GetMessageW(&msg, NULL, 0, 0); + if (result == 0) { + PostQuitMessage(msg.wParam); + /* What to do here? */ + } else if (result != (DWORD)-1) { + TranslateMessage(&msg); + DispatchMessageW(&msg); + } + } + ResetEvent(tsdPtr->event); +#endif if (waitForFiles && tsdPtr->onList) { /* * Remove the ThreadSpecificData structure of this thread from the @@ -1071,7 +1210,11 @@ NotifierThreadProc( tsdPtr->onList = 0; tsdPtr->pollState = 0; } - Tcl_ConditionNotify(&tsdPtr->waitCV); +#ifdef __CYGWIN__ + PostMessageW(tsdPtr->hwnd, 1024, 0, 0); +#else /* __CYGWIN__ */ + Tcl_ConditionNotify(&tsdPtr->waitCV); +#endif /* __CYGWIN__ */ } } Tcl_MutexUnlock(¬ifierMutex); |