| ︙ | | |
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
|
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
|
+
+
+
+
+
+
+
|
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. */
#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. */
#endif
} ThreadSpecificData;
static Tcl_ThreadDataKey dataKey;
|
| ︙ | | |
200
201
202
203
204
205
206
207
208
209
210
211
212
213
|
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
|
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
|
* Returns a handle to the notifier state for this thread.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
#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)
{
ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
#ifdef TCL_THREADS
|
| ︙ | | |
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
|
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
|
+
+
+
+
|
}
}
/*
* 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(¬ifierMutex);
#endif
}
/*
*----------------------------------------------------------------------
|
| ︙ | | |
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
|
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
|
+
+
+
+
|
Tcl_AlertNotifier(
ClientData clientData)
{
#ifdef TCL_THREADS
ThreadSpecificData *tsdPtr = (ThreadSpecificData *) clientData;
Tcl_MutexLock(¬ifierMutex);
tsdPtr->eventReady = 1;
#ifdef __CYGWIN__
PostMessageW(tsdPtr->hwnd, 1024, 0, 0);
#else
Tcl_ConditionNotify(&tsdPtr->waitCV);
#endif
Tcl_MutexUnlock(¬ifierMutex);
#endif
}
/*
*----------------------------------------------------------------------
*
|
| ︙ | | |
637
638
639
640
641
642
643
644
645
646
647
648
649
650
|
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
|
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
|
(*filePtr->proc)(filePtr->clientData, mask);
}
break;
}
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__ */
/*
*----------------------------------------------------------------------
*
* Tcl_WaitForEvent --
*
* This function is called by Tcl_DoOneEvent to wait for new events on
* the message queue. If the block time is 0, then Tcl_WaitForEvent just
|
| ︙ | | |
665
666
667
668
669
670
671
672
673
674
675
676
677
678
|
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
|
+
+
+
|
{
FileHandler *filePtr;
FileHandlerEvent *fileEvPtr;
int mask;
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 are
* not enabled. They are the arguments for the regular select() used when
* the core is not thread-enabled.
*/
|
| ︙ | | |
752
753
754
755
756
757
758
759
760
761
762
763
764
765
|
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
|
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
|
tsdPtr->pollState = POLL_WANT;
timePtr = NULL;
} else {
waitForFiles = (tsdPtr->numFdBits > 0);
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 of
* ThreadSpecificData structures of all threads that are waiting on
* file events.
*/
|
| ︙ | | |
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
|
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
|
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
|
}
FD_ZERO(&(tsdPtr->readyMasks.readable));
FD_ZERO(&(tsdPtr->readyMasks.writable));
FD_ZERO(&(tsdPtr->readyMasks.exceptional));
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
* waiting list. Alert the notifier thread to recompute its select
* masks - skipping this caused a hang when trying to close a pipe
* which the notifier thread was still doing a select on.
|
| ︙ | | |
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
|
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
|
+
+
+
-
+
+
|
if (tsdPtr->nextPtr) {
tsdPtr->nextPtr->prevPtr = tsdPtr->prevPtr;
}
tsdPtr->nextPtr = tsdPtr->prevPtr = NULL;
tsdPtr->onList = 0;
tsdPtr->pollState = 0;
}
#ifdef __CYGWIN__
PostMessageW(tsdPtr->hwnd, 1024, 0, 0);
#else /* __CYGWIN__ */
Tcl_ConditionNotify(&tsdPtr->waitCV);
Tcl_ConditionNotify(&tsdPtr->waitCV);
#endif /* __CYGWIN__ */
}
}
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
|
| ︙ | | |