archie/tcl7.6/doc/Notifier.3
2024-05-27 16:40:40 +02:00

371 lines
16 KiB
Groff

'\"
'\" Copyright (c) 1995-1996 Sun Microsystems, Inc.
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\"
'\" SCCS: @(#) Notifier.3 1.11 96/06/05 18:00:17
'\"
.so man.macros
.TH Tcl_CreateEventSource 3 7.5 Tcl "Tcl Library Procedures"
.BS
.SH NAME
Tcl_CreateEventSource, Tcl_DeleteEventSource, Tcl_WatchFile, Tcl_FileReady, Tcl_SetMaxBlockTime, Tcl_QueueEvent, Tcl_WaitForEvent \- Event sources, the event notifier, and the event queue
.SH SYNOPSIS
.nf
\fB#include <tcl.h>\fR
.sp
\fBTcl_CreateEventSource(\fIsetupProc, checkProc, clientData\fB)\fR
.sp
\fBTcl_DeleteEventSource(\fIsetupProc, checkProc, clientData\fB)\fR
.sp
\fBTcl_WatchFile(\fIfile, mask\fB)\fR
.sp
\fBTcl_SetMaxBlockTime(\fItimePtr\fB)\fR
.sp
int
\fBTcl_FileReady(\fIfile, mask\fB)\fR
.sp
\fBTcl_QueueEvent(\fIevPtr, position\fB)\fR
.sp
int
\fBTcl_WaitForEvent(\fItimePtr\fB)\fR
.SH ARGUMENTS
.AS Tcl_EventSetupProc *setupProc
.AP Tcl_EventSetupProc *setupProc in
Procedure to invoke to prepare for event wait in \fBTcl_DoWhenIdle\fR.
.AP Tcl_EventCheckProc *checkProc in
Procedure for \fBTcl_DoWhenIdle\fR to invoke after waiting for
events. Checks to see if any events have occurred and, if so,
queues them.
.AP ClientData clientData in
Arbitrary one-word value to pass to \fIsetupProc\fR and \fIcheckProc\fR.
.AP Tcl_File file in
Generic file handle as returned by \fBTcl_GetFile\fR.
.AP int mask in
Indicates the events of interest on \fIfile\fR: an OR'ed combination
of \fBTCL_READABLE\fR, \fBTCL_WRITABLE\fR, and \fBTCL_EXCEPTION\fR.
.AP Tcl_Time *timePtr in
Indicates the maximum amount of time to wait for an event. This
is specified as an interval (how long to wait), not an absolute
time (when to wakeup). If the pointer passed to \fBTcl_WaitForEvent\fR
is NULL, it means there is no maximum wait time: wait forever if
necessary.
.AP Tcl_Event *evPtr in
An event to add to the event queue. The storage for the event must
.VS
have been allocated by the caller using \fBTcl_Alloc\fR or \fBckalloc\fR.
.VE
.AP Tcl_QueuePosition position in
Where to add the new event in the queue: \fBTCL_QUEUE_TAIL\fR,
\fBTCL_QUEUE_HEAD\fR, or \fBTCL_QUEUE_MARK\fR.
.AP int flags in
A copy of the \fIflags\fR argument passed to \fBTcl_DoOneEvent\fR.
.BE
.SH INTRODUCTION
.PP
The procedures described here are the building blocks out of which
the Tcl event notifier is constructed. The event notifier is the
lowest layer in the Tcl event mechanism. It consists of three
things:
.IP [1]
Event sources: these represent the ways in which events can be
generated. For example, there is a timer event source that implements
the \fBTcl_CreateTimerHandler\fR procedure and the \fBafter\fR command,
and there is a file event source that implements the
\fBTcl_CreateFileHandler\fR procedure. An event source must work
with the notifier to detect events at the right times, record them
on the event queue, and eventually notify higher-level software that
they have occurred.
.IP [2]
The event queue: there is a single queue for the whole application,
containing events that have been detected but not yet serviced.
The event queue guarantees a fair discipline of event handling, so
that no event source can starve the others. It also allows events
to be saved for servicing at a future time.
.IP [3]
The procedure \fBTcl_DoOneEvent\fR: this is procedure that is invoked
by the application to service events. It works with the event sources
and the event queue to detect and handle events, and calls
\fBTcl_WaitForEvent\fR to actually wait for an event to occur.
.PP
The easiest way to understand how the notifier works is to consider
what happens when \fBTcl_DoOneEvent\fR is called.
\fBTcl_DoOneEvent\fR is passed a \fIflags\fR
argument that indicates what sort of events it is OK to process and
also whether or not to block if no events are ready.
\fBTcl_DoOneEvent\fR does the following things:
.IP [1]
Check the event queue to see if it contains any events that can
be serviced. If so, service the first possible event, remove it
from the queue, and return.
.IP [2]
Prepare to block for an event. To do this, \fBTcl_DoOneEvent\fR
invokes a \fIsetup procedure\fR in each event source.
The event source will call procedures like \fBTcl_WatchFile\fR and
\fBTcl_SetMaxBlockTime\fR to indicate what low-level events to look
for in \fBTcl_WaitForEvent\fR.
.IP [3]
Call \fBTcl_WaitForEvent\fR. This procedure is implemented differently
on different platforms; it waits for an event to occur, based on the
information provided by the event sources.
It may cause the application to block if \fItimePtr\fR specifies
an interval other than 0.
\fBTcl_WaitForEvent\fR returns when something has happened,
such as a file becoming readable or the interval given by \fItimePtr\fR
expiring. If there are no events for \fBTcl_WaitForEvent\fR to
wait for, so that it would block forever, then it returns immediately
and \fBTcl_DoOneEvent\fR returns 0.
.IP [4]
Call a \fIcheck procedure\fR in each event source. The check
procedure determines whether any events of interest to this source
occurred (e.g. by calling \fBTcl_FileReady\fR). If so,
the events are added to the event queue.
.IP [5]
Check the event queue to see if it contains any events that can
be serviced. If so, service the first possible event, remove it
from the queue, and return.
.IP [6]
See if there are idle callbacks pending.
If so, invoke all of them and return.
.IP [7]
Either return 0 to indicate that no events were ready, or go back to
step [2] if blocking was requested by the caller.
.PP
The procedures in this file allow you to do two things. First, they
allow you to create new event sources, such as one for UNIX signals
or one to notify when subprocesses have exited. Second, the procedures
can be used to build a new version of \fBTcl_DoOneEvent\fR. This
might be necessary to support a new operating system with different
low-level event reporting mechanisms, or it might be necessary to
merge Tcl's event loop with that of some other toolkit like Xt.
.SH "CREATING A NEW EVENT SOURCE"
.PP
An event source consists of three procedures invoked by the notifier,
plus additional C procedures that are invoked by higher-level code
to arrange for event-driven callbacks. The three procedures called
by the notifier consist of the setup and check procedures described
above, plus an additional procedure that is invoked when an event
is removed from the event queue for servicing.
.PP
The procedure \fBTcl_CreateEventSource\fR creates a new event source.
Its arguments specify the setup procedure and check procedure for
the event source.
\fISetupProc\fR should match the following prototype:
.CS
typedef void Tcl_EventSetupProc(
ClientData \fIclientData\fR,
int \fIflags\fR);
.CE
The \fIclientData\fR argument will be the same as the \fIclientData\fR
argument to \fBTcl_CreateEventSource\fR; it is typically used to
point to private information managed by the event source.
The \fIflags\fR argument will be the same as the \fIflags\fR
argument passed to \fBTcl_DoOneEvent\fR except that it will never
by 0 (\fBTcl_DoOneEvent\fR replaces 0 with \fBTCL_ALL_EVENTS\fR).
\fIFlags\fR indicates what kinds of events should be considered;
if the bit corresponding to this event source isn't set, the event
source should return immediately without doing anything. For
example, the file event source checks for the \fBTCL_FILE_EVENTS\fR
bit.
.PP
\fISetupProc\fR's job is to provide information to
\fBTcl_WaitForEvent\fR about how to wait for events.
It usually does this by calling \fBTcl_WatchFile\fR or
\fBTcl_SetMaxBlockTime\fR.
For example, \fIsetupProc\fR can call \fBTcl_WatchFile\fR to indicate
that \fBTcl_WaitForEvent\fR should return when the conditions
given by the \fImask\fR argument become true for the file given
by \fIfile\fR.
The UNIX version of \fBTcl_WaitForEvent\fR uses the
information passed to \fBTcl_WatchFile\fR to set the file masks
for \fBselect\fR, which it uses to wait for events.
If \fBTcl_WatchFile\fR isn't called by any event sources then
\fBTcl_WaitForEvent\fR will ignore files while waiting.
.PP
\fISetupProc\fR can also invoke \fBTcl_SetMaxBlockTime\fR to set an
upper bound on how long \fBTcl_WaitForEvent\fR will block.
If no event source calls \fBTcl_SetMaxBlockTime\fR then
\fBTcl_WaitForEvent\fR will wait as long as necessary for an event
to occur; otherwise, it will only wait as long as the shortest
interval passed to \fBTcl_SetMaxBlockTime\fR by one of the event
sources.
For example, the timer event source uses this procedure to limit the
wait time to the interval before the next timer event is ready.
If an event source knows that it already has events ready to report,
it can request a zero maximum block time.
The \fItimePtr\fR argument to \fBTcl_WaitForEvent\fR points to
a structure that describes a time interval in seconds and
microseconds:
.CS
typedef struct Tcl_Time {
long \fIsec\fR;
long \fIusec\fR;
} Tcl_Time;
.CE
The \fIusec\fR field should be less than 1000000.
.PP
Information provided to \fBTcl_WatchFile\fR and \fBTcl_SetMaxBlockTime\fR
is only used for the next call to \fBTcl_WaitForEvent\fR; it is
discarded after \fBTcl_WaitForEvent\fR returns.
The next time an event wait is done each of the event sources'
setup procedures will be called again, and they can specify new
information for that event wait.
.PP
In addition to the generic procedures \fBTcl_WatchFile\fR and
\fBTcl_SetMaxBlockTime\fR, other platform-specific procedures may
also be available for \fIsetupProc\fR, if there is additional
information needed by \fBTcl_WaitForEvent\fR on that platform.
.PP
The second procedure provided by each event source is its check
procedure, indicated by the \fIcheckProc\fR argument to
\fBTcl_CreateEventSource\fR. \fICheckProc\fR must match the
following prototype:
.CS
typedef void Tcl_EventCheckProc(
ClientData \fIclientData\fR,
int \fIflags\fR);
.CE
The arguments to this procedure are the same as those for \fIsetupProc\fR.
\fBCheckProc\fR is invoked by \fBTcl_DoOneEvent\fR after it has waited
for events. Presumably at least one event source is now prepared to
queue an event. \fBTcl_DoOneEvent\fR calls each of the event sources
in turn, so they all have a chance to queue any events that are ready.
The check procedure does two things. First, it must see if any events
have triggered. Different event sources do this in different ways,
but the procedure \fBTcl_FileReady\fR may be useful for some event
sources. It takes as arguments a file identifier \fIfile\fR and
a mask of interesting conditions; it returns another mask indicating
which of those conditions were found to be present on the file during
the most recent call to \fBTcl_WaitForEvent\fR.
\fBTcl_WaitForEvent\fR only checks a file if \fBTcl_WatchFile\fR was
called by at least one event source, so it is possible for
\fBTcl_FileReady\fR to return 0 even if the file is ready.
.PP
If an event source's check procedure detects that an interesting
event has occurred, then it must add the event to Tcl's event queue.
To do this, the event source calls \fBTcl_QueueEvent\fR.
The \fIevPtr\fR argument is a pointer to a dynamically allocated
structure containing the event (see below for more information
on memory management issues).
Each event source can define its own event structure with
whatever information is relevant to that event source.
However, the first element of the structure must be a structure
of type \fBTcl_Event\fR, and the address of this structure is used when
communicating between the event source and the rest of the notifier.
A \fBTcl_Event\fR has the following definition:
.CS
typedef struct Tcl_Event {
Tcl_EventProc *\fIproc\fR;
struct Tcl_Event *\fInextPtr\fR;
};
.CE
The event source must fill in the \fIproc\fR field of
the event before calling \fBTcl_QueueEvent\fR.
The \fInextPtr\fR is used to link together the events in the queue
and should not be modified by the event source.
.PP
An event may be added to the queue at any of three positions, depending
on the \fIposition\fR argument to \fBTcl_QueueEvent\fR:
.IP \fBTCL_QUEUE_TAIL\fR 24
Add the event at the back of the queue, so that all other pending
events will be serviced first. This is almost always the right
place for new events.
.IP \fBTCL_QUEUE_HEAD\fR 24
Add the event at the front of the queue, so that it will be serviced
before all other queued events.
.IP \fBTCL_QUEUE_MARK\fR 24
Add the event at the front of the queue, unless there are other
events at the front whose position is \fBTCL_QUEUE_MARK\fR; if so,
add the new event just after all other \fBTCL_QUEUE_MARK\fR events.
This value of \fIposition\fR is used to insert an ordered sequence of
events at the front of the queue, such as a series of
Enter and Leave events synthesized during a grab or ungrab operation
in Tk.
.PP
When it is time to handle an event from the queue (steps 1 and 5
above) \fBTcl_DoOneEvent\fR will invoke the \fIproc\fR specified
in the first queued \fBTcl_Event\fR structure.
\fIProc\fR must match the following prototype:
.CS
typedef int Tcl_EventProc(
Tcl_Event *\fIevPtr\fR,
int \fIflags\fR);
.CE
The first argument to \fIproc\fR is a pointer to the event, which will
be the same as the first argument to the \fBTcl_QueueEvent\fR call that
added the event to the queue.
The second argument to \fIproc\fR is the \fIflags\fR argument for the
current call to \fBTcl_DoOneEvent\fR; this is used by the event source
to return immediately if its events are not relevant.
.PP
It is up to \fIproc\fR to handle the event, typically by invoking
one or more Tcl commands or C-level callbacks.
Once the event source has finished handling the event it returns 1
to indicate that the event can be removed from the queue.
If for some reason the event source decides that the event cannot
be handled at this time, it may return 0 to indicate that the event
should be deferred for processing later; in this case \fBTcl_DoOneEvent\fR
will go on to the next event in the queue and attempt to service it.
There are several reasons why an event source might defer an event.
One possibility is that events of this type are excluded by the
\fIflags\fR argument.
For example, the file event source will always return 0 if the
\fBTCL_FILE_EVENTS\fR bit isn't set in \fIflags\fR.
Another example of deferring events happens in Tk if
\fBTk_RestrictEvents\fR has been invoked to defer certain kinds
of window events.
.PP
When \fIproc\fR returns 1, \fBTcl_DoOneEvent\fR will remove the
event from the event queue and free its storage.
Note that the storage for an event must be allocated by
.VS
the event source (using \fBTcl_Alloc\fR or the Tcl macro \fBckalloc\fR)
.VE
before calling \fBTcl_QueueEvent\fR, but it
will be freed by \fBTcl_DoOneEvent\fR, not by the event source.
.SH "CREATING A NEW NOTIFIER"
.PP
The notifier consists of all the procedures described in this
manual entry, plus \fBTcl_DoOneEvent\fR and \fBTcl_Sleep\fR.
Most of these procedures are generic, in that they are the
same for all platforms. However, four of the procedures are
platform-dependent: \fBTcl_WatchFile\fR,
\fBTcl_FileReady\fR, \fBTcl_WaitForEvent\fR, and \fBTcl_Sleep\fR.
To support a new platform, you must write new versions of these
procedures.
\fBTcl_WatchFile\fR and \fBTcl_FileReady\fR have already been
described previously in this document, and \fBTcl_Sleep\fR
is described in its own manual entry.
.PP
\fBTcl_WaitForEvent\fR is the lowest-level procedure in the
notifier; it is responsible for waiting for an ``interesting''
event to occur or for a given time to elapse.
Before \fBTcl_WaitForEvent\fR is invoked, each of the event
sources' setup procedure will have been invoked; the setup
procedures will have provided information about what to wait
for by invoking procedures like \fBTcl_WatchFile\fR.
The \fItimePtr\fR argument to \fBTcl_WaitForEvent\fR gives
the maximum time to block for an event, based on calls to
\fBTcl_SetMaxBlockTime\fR made by setup procedures and
on other information (such as the \fBTCL_DONT_WAIT\fR bit in \fIflags\fR).
\fBTcl_WaitForEvent\fR uses information saved by \fBTcl_WatchFile\fR,
plus the \fItimePtr\fR argument to decide what to wait for
and how long to block.
It returns TCL_OK as soon as one of the specified events has occurred
or the given amount of time has elapsed.
However, if there are no event handlers (neither \fBTcl_WatchFile\fR nor
\fBTcl_SetMaxBlockTime\fR has been called since the last call to
\fBTcl_WaitForEvent\fR), so that the procedure would block forever,
then it returns immediately with a result of TCL_ERROR.
.PP
The easiest way to create a new notifier is to look at the code
for an existing notifier, such as the files \fBgeneric/tclNotify.c\fR
and \fBunix/tclUnixNotfy.c\fR.
.SH KEYWORDS
block time, event notifier, event queue, event sources, file events