1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
/*
* tclUnixNotify.c --
*
* This file contains the implementation of the select()-based
* Unix-specific notifier, which is the lowest-level part of the Tcl
* event loop. This file works together with generic/tclNotify.c.
*
* Copyright (c) 1995-1997 Sun Microsystems, Inc.
*
* See the file "license.terms" for information on usage and redistribution of
* this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
* RCS: @(#) $Id: tclUnixNotfy.c,v 1.28 2005/07/24 22:56:44 dkf Exp $
*/
#ifndef HAVE_COREFOUNDATION /* Darwin/Mac OS X CoreFoundation notifier is
* in tclMacOSXNotify.c */
#include "tclInt.h"
#include <signal.h>
/*
* This code does deep stub magic to allow replacement of the notifier at
* runtime.
*/
extern TclStubs tclStubs;
|
|
|
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
/*
* tclUnixNotify.c --
*
* This file contains the implementation of the select()-based
* Unix-specific notifier, which is the lowest-level part of the Tcl
* event loop. This file works together with generic/tclNotify.c.
*
* Copyright (c) 1995-1997 Sun Microsystems, Inc.
*
* See the file "license.terms" for information on usage and redistribution of
* this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
* RCS: @(#) $Id: tclUnixNotfy.c,v 1.29 2005/11/02 23:26:50 dkf Exp $
*/
#ifndef HAVE_COREFOUNDATION /* Darwin/Mac OS X CoreFoundation notifier is
* in tclMacOSXNotify.c */
#include "tclInt.h"
#include <signal.h>
/*
* This code does deep stub magic to allow replacement of the notifier at
* runtime.
*/
extern TclStubs tclStubs;
|
| ︙ | | | ︙ | |
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
|
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
ClientData
Tcl_InitNotifier()
{
ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
#ifdef TCL_THREADS
tsdPtr->eventReady = 0;
/*
|
|
|
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
|
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
ClientData
Tcl_InitNotifier(void)
{
ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
#ifdef TCL_THREADS
tsdPtr->eventReady = 0;
/*
|
| ︙ | | | ︙ | |
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
|
* May terminate the background notifier thread if this is the last
* notifier instance.
*
*----------------------------------------------------------------------
*/
void
Tcl_FinalizeNotifier(clientData)
ClientData clientData; /* Not used. */
{
#ifdef TCL_THREADS
ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
Tcl_MutexLock(¬ifierMutex);
notifierCount--;
|
|
|
|
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
|
* May terminate the background notifier thread if this is the last
* notifier instance.
*
*----------------------------------------------------------------------
*/
void
Tcl_FinalizeNotifier(
ClientData clientData) /* Not used. */
{
#ifdef TCL_THREADS
ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
Tcl_MutexLock(¬ifierMutex);
notifierCount--;
|
| ︙ | | | ︙ | |
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
|
* Side effects:
* Signals the notifier condition variable for the specified notifier.
*
*----------------------------------------------------------------------
*/
void
Tcl_AlertNotifier(clientData)
ClientData clientData;
{
#ifdef TCL_THREADS
ThreadSpecificData *tsdPtr = (ThreadSpecificData *) clientData;
Tcl_MutexLock(¬ifierMutex);
tsdPtr->eventReady = 1;
Tcl_ConditionNotify(&tsdPtr->waitCV);
Tcl_MutexUnlock(¬ifierMutex);
|
|
|
|
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
|
* Side effects:
* Signals the notifier condition variable for the specified notifier.
*
*----------------------------------------------------------------------
*/
void
Tcl_AlertNotifier(
ClientData clientData)
{
#ifdef TCL_THREADS
ThreadSpecificData *tsdPtr = (ThreadSpecificData *) clientData;
Tcl_MutexLock(¬ifierMutex);
tsdPtr->eventReady = 1;
Tcl_ConditionNotify(&tsdPtr->waitCV);
Tcl_MutexUnlock(¬ifierMutex);
|
| ︙ | | | ︙ | |
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
|
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
void
Tcl_SetTimer(timePtr)
Tcl_Time *timePtr; /* Timeout value, may be NULL. */
{
/*
* The interval timer doesn't do anything in this implementation, because
* the only event loop is via Tcl_DoOneEvent, which passes timeout values
* to Tcl_WaitForEvent.
*/
|
|
|
|
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
|
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
void
Tcl_SetTimer(
Tcl_Time *timePtr) /* Timeout value, may be NULL. */
{
/*
* The interval timer doesn't do anything in this implementation, because
* the only event loop is via Tcl_DoOneEvent, which passes timeout values
* to Tcl_WaitForEvent.
*/
|
| ︙ | | | ︙ | |
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
|
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
void
Tcl_ServiceModeHook(mode)
int mode; /* Either TCL_SERVICE_ALL, or
* TCL_SERVICE_NONE. */
{
}
/*
*----------------------------------------------------------------------
*
|
|
|
|
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
|
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
void
Tcl_ServiceModeHook(
int mode) /* Either TCL_SERVICE_ALL, or
* TCL_SERVICE_NONE. */
{
}
/*
*----------------------------------------------------------------------
*
|
| ︙ | | | ︙ | |
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
|
* Side effects:
* Creates a new file handler structure.
*
*----------------------------------------------------------------------
*/
void
Tcl_CreateFileHandler(fd, mask, proc, clientData)
int fd; /* Handle of stream to watch. */
int mask; /* OR'ed combination of TCL_READABLE,
* TCL_WRITABLE, and TCL_EXCEPTION: indicates
* conditions under which proc should be
* called. */
Tcl_FileProc *proc; /* Function to call for each selected
* event. */
ClientData clientData; /* Arbitrary data to pass to proc. */
{
ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
FileHandler *filePtr;
if (tclStubs.tcl_CreateFileHandler != tclOriginalNotifier.createFileHandlerProc) {
tclStubs.tcl_CreateFileHandler(fd, mask, proc, clientData);
return;
|
|
|
|
|
|
|
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
|
* Side effects:
* Creates a new file handler structure.
*
*----------------------------------------------------------------------
*/
void
Tcl_CreateFileHandler(
int fd, /* Handle of stream to watch. */
int mask, /* OR'ed combination of TCL_READABLE,
* TCL_WRITABLE, and TCL_EXCEPTION: indicates
* conditions under which proc should be
* called. */
Tcl_FileProc *proc, /* Function to call for each selected
* event. */
ClientData clientData) /* Arbitrary data to pass to proc. */
{
ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
FileHandler *filePtr;
if (tclStubs.tcl_CreateFileHandler != tclOriginalNotifier.createFileHandlerProc) {
tclStubs.tcl_CreateFileHandler(fd, mask, proc, clientData);
return;
|
| ︙ | | | ︙ | |
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
|
* Side effects:
* If a callback was previously registered on file, remove it.
*
*----------------------------------------------------------------------
*/
void
Tcl_DeleteFileHandler(fd)
int fd; /* Stream id for which to remove callback
* function. */
{
FileHandler *filePtr, *prevPtr;
int i;
ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
if (tclStubs.tcl_DeleteFileHandler != tclOriginalNotifier.deleteFileHandlerProc) {
|
|
|
|
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
|
* Side effects:
* If a callback was previously registered on file, remove it.
*
*----------------------------------------------------------------------
*/
void
Tcl_DeleteFileHandler(
int fd) /* Stream id for which to remove callback
* function. */
{
FileHandler *filePtr, *prevPtr;
int i;
ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
if (tclStubs.tcl_DeleteFileHandler != tclOriginalNotifier.deleteFileHandlerProc) {
|
| ︙ | | | ︙ | |
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
|
* Side effects:
* Whatever the file handler's callback function does.
*
*----------------------------------------------------------------------
*/
static int
FileHandlerEventProc(evPtr, flags)
Tcl_Event *evPtr; /* Event to service. */
int flags; /* Flags that indicate what events to handle,
* such as TCL_FILE_EVENTS. */
{
int mask;
FileHandler *filePtr;
FileHandlerEvent *fileEvPtr = (FileHandlerEvent *) evPtr;
ThreadSpecificData *tsdPtr;
|
|
|
|
|
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
|
* Side effects:
* Whatever the file handler's callback function does.
*
*----------------------------------------------------------------------
*/
static int
FileHandlerEventProc(
Tcl_Event *evPtr, /* Event to service. */
int flags) /* Flags that indicate what events to handle,
* such as TCL_FILE_EVENTS. */
{
int mask;
FileHandler *filePtr;
FileHandlerEvent *fileEvPtr = (FileHandlerEvent *) evPtr;
ThreadSpecificData *tsdPtr;
|
| ︙ | | | ︙ | |
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
|
* Side effects:
* Queues file events that are detected by the select.
*
*----------------------------------------------------------------------
*/
int
Tcl_WaitForEvent(timePtr)
Tcl_Time *timePtr; /* Maximum block time, or NULL. */
{
FileHandler *filePtr;
FileHandlerEvent *fileEvPtr;
int mask;
Tcl_Time myTime;
#ifdef TCL_THREADS
int waitForFiles;
|
|
|
|
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
|
* Side effects:
* Queues file events that are detected by the select.
*
*----------------------------------------------------------------------
*/
int
Tcl_WaitForEvent(
Tcl_Time *timePtr) /* Maximum block time, or NULL. */
{
FileHandler *filePtr;
FileHandlerEvent *fileEvPtr;
int mask;
Tcl_Time myTime;
#ifdef TCL_THREADS
int waitForFiles;
|
| ︙ | | | ︙ | |
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
|
* The trigger pipe used to signal the notifier thread is created when
* the notifier thread first starts.
*
*----------------------------------------------------------------------
*/
static void
NotifierThreadProc(clientData)
ClientData clientData; /* Not used. */
{
ThreadSpecificData *tsdPtr;
fd_set readableMask;
fd_set writableMask;
fd_set exceptionalMask;
int fds[2];
int i, status, numFdBits = 0, receivePipe;
|
|
|
|
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
|
* The trigger pipe used to signal the notifier thread is created when
* the notifier thread first starts.
*
*----------------------------------------------------------------------
*/
static void
NotifierThreadProc(
ClientData clientData) /* Not used. */
{
ThreadSpecificData *tsdPtr;
fd_set readableMask;
fd_set writableMask;
fd_set exceptionalMask;
int fds[2];
int i, status, numFdBits = 0, receivePipe;
|
| ︙ | | | ︙ | |