summaryrefslogtreecommitdiffstats
path: root/unix/tclUnixNotfy.c
diff options
context:
space:
mode:
authorjan.nijtmans <nijtmans@users.sourceforge.net>2012-06-23 06:59:17 (GMT)
committerjan.nijtmans <nijtmans@users.sourceforge.net>2012-06-23 06:59:17 (GMT)
commit366ea66bb84ae5120d3dca0dc01fb7aa46fc9ee6 (patch)
tree722cc30485f2241d93370d01c151c631e4c784e9 /unix/tclUnixNotfy.c
parentb6f50b1321a5cd34af747eb670aad924fc66d7b7 (diff)
parent5680fa44dbfafeed01f328dd8cde4310c3c95ba6 (diff)
downloadtcl-366ea66bb84ae5120d3dca0dc01fb7aa46fc9ee6.zip
tcl-366ea66bb84ae5120d3dca0dc01fb7aa46fc9ee6.tar.gz
tcl-366ea66bb84ae5120d3dca0dc01fb7aa46fc9ee6.tar.bz2
[Bug 3508771]: Cygwin notifier for handling win32 events
Diffstat (limited to 'unix/tclUnixNotfy.c')
-rw-r--r--unix/tclUnixNotfy.c145
1 files changed, 144 insertions, 1 deletions
diff --git a/unix/tclUnixNotfy.c b/unix/tclUnixNotfy.c
index 0af7207..128b080 100644
--- a/unix/tclUnixNotfy.c
+++ b/unix/tclUnixNotfy.c
@@ -98,9 +98,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. */
@@ -205,6 +212,48 @@ static int FileHandlerEventProc _ANSI_ARGS_((Tcl_Event *evPtr,
*----------------------------------------------------------------------
*/
+#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()
{
@@ -304,7 +353,11 @@ Tcl_FinalizeNotifier(clientData)
* Clean up any synchronization objects in the thread local storage.
*/
+#ifdef __CYGWIN__
+ CloseHandle(tsdPtr->event);
+#else /* __CYGWIN__ */
Tcl_ConditionFinalize(&(tsdPtr->waitCV));
+#endif /* __CYGWIN__ */
Tcl_MutexUnlock(&notifierMutex);
#endif
@@ -339,7 +392,11 @@ Tcl_AlertNotifier(clientData)
ThreadSpecificData *tsdPtr = (ThreadSpecificData *) clientData;
Tcl_MutexLock(&notifierMutex);
tsdPtr->eventReady = 1;
+#ifdef __CYGWIN__
+ PostMessageW(tsdPtr->hwnd, 1024, 0, 0);
+#else
Tcl_ConditionNotify(&tsdPtr->waitCV);
+#endif
Tcl_MutexUnlock(&notifierMutex);
#endif
}
@@ -635,6 +692,31 @@ FileHandlerEventProc(evPtr, flags)
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__ */
+
/*
*----------------------------------------------------------------------
*
@@ -663,6 +745,9 @@ Tcl_WaitForEvent(timePtr)
int mask;
#ifdef TCL_THREADS
int waitForFiles;
+# ifdef __CYGWIN__
+ MSG msg;
+# endif
#else
/* Impl. notes: timeout & timeoutPtr are used if, and only if
* threads are not enabled. They are the arguments for the regular
@@ -738,6 +823,29 @@ Tcl_WaitForEvent(timePtr)
tsdPtr->pollState = 0;
}
+#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
if (waitForFiles) {
/*
* Add the ThreadSpecificData structure of this thread to the list
@@ -762,10 +870,41 @@ Tcl_WaitForEvent(timePtr)
FD_ZERO( &(tsdPtr->readyMasks.exceptional) );
if (!tsdPtr->eventReady) {
- Tcl_ConditionWait(&tsdPtr->waitCV, &notifierMutex, timePtr);
+#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(&notifierMutex);
+ MsgWaitForMultipleObjects(1, &tsdPtr->event, 0, timeout, 1279);
+ Tcl_MutexLock(&notifierMutex);
+ }
+#else
+ Tcl_ConditionWait(&tsdPtr->waitCV, &notifierMutex, 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
@@ -1040,7 +1179,11 @@ NotifierThreadProc(clientData)
tsdPtr->onList = 0;
tsdPtr->pollState = 0;
}
+#ifdef __CYGWIN__
+ PostMessageW(tsdPtr->hwnd, 1024, 0, 0);
+#else /* __CYGWIN__ */
Tcl_ConditionNotify(&tsdPtr->waitCV);
+#endif /* __CYGWIN__ */
}
}
Tcl_MutexUnlock(&notifierMutex);