Tcl Library Procedures
NAME
Tcl_CreateEventSource, Tcl_DeleteEventSource, Tcl_WatchFile, Tcl_FileReady, Tcl_SetMaxBlockTime, Tcl_QueueEvent, Tcl_WaitForEvent - Event sources, the event notifier, and the event queue
SYNOPSIS
#include <tcl.h>
Tcl_CreateEventSource(setupProc, checkProc, clientData)
Tcl_DeleteEventSource(setupProc, checkProc, clientData)
Tcl_WatchFile(file, mask)
Tcl_SetMaxBlockTime(timePtr)
int
Tcl_FileReady(file, mask)
Tcl_QueueEvent(evPtr, position)
int
Tcl_WaitForEvent(timePtr)
ARGUMENTS
-
Tcl_EventSetupProc *setupProc (in)
-
Procedure to invoke to prepare for event wait in Tcl_DoWhenIdle.
-
Tcl_EventCheckProc *checkProc (in)
-
Procedure for Tcl_DoWhenIdle to invoke after waiting for
events. Checks to see if any events have occurred and, if so,
queues them.
-
ClientData clientData (in)
-
Arbitrary one-word value to pass to setupProc and checkProc.
-
Tcl_File file (in)
-
Generic file handle as returned by Tcl_GetFile.
-
int mask (in)
-
Indicates the events of interest on file: an OR'ed combination
of TCL_READABLE, TCL_WRITABLE, and TCL_EXCEPTION.
-
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 Tcl_WaitForEvent
is NULL, it means there is no maximum wait time: wait forever if
necessary.
-
Tcl_Event *evPtr (in)
-
An event to add to the event queue. The storage for the event must
have been allocated by the caller using Tcl_Alloc or ckalloc.
-
Tcl_QueuePosition position (in)
-
Where to add the new event in the queue: TCL_QUEUE_TAIL,
TCL_QUEUE_HEAD, or TCL_QUEUE_MARK.
-
int flags (in)
-
A copy of the flags argument passed to Tcl_DoOneEvent.
INTRODUCTION
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:
-
Event sources: these represent the ways in which events can be
generated. For example, there is a timer event source that implements
the Tcl_CreateTimerHandler procedure and the after command,
and there is a file event source that implements the
Tcl_CreateFileHandler 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.
-
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.
-
The procedure Tcl_DoOneEvent: 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
Tcl_WaitForEvent to actually wait for an event to occur.
-
The easiest way to understand how the notifier works is to consider
what happens when Tcl_DoOneEvent is called.
Tcl_DoOneEvent is passed a flags
argument that indicates what sort of events it is OK to process and
also whether or not to block if no events are ready.
Tcl_DoOneEvent does the following things:
-
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.
-
Prepare to block for an event. To do this, Tcl_DoOneEvent
invokes a setup procedure in each event source.
The event source will call procedures like Tcl_WatchFile and
Tcl_SetMaxBlockTime to indicate what low-level events to look
for in Tcl_WaitForEvent.
-
Call Tcl_WaitForEvent. 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 timePtr specifies
an interval other than 0.
Tcl_WaitForEvent returns when something has happened,
such as a file becoming readable or the interval given by timePtr
expiring. If there are no events for Tcl_WaitForEvent to
wait for, so that it would block forever, then it returns immediately
and Tcl_DoOneEvent returns 0.
-
Call a check procedure in each event source. The check
procedure determines whether any events of interest to this source
occurred (e.g. by calling Tcl_FileReady). If so,
the events are added to the event queue.
-
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.
-
See if there are idle callbacks pending.
If so, invoke all of them and return.
-
Either return 0 to indicate that no events were ready, or go back to
step [2] if blocking was requested by the caller.
-
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 Tcl_DoOneEvent. 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.
CREATING A NEW EVENT SOURCE
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.
The procedure Tcl_CreateEventSource creates a new event source.
Its arguments specify the setup procedure and check procedure for
the event source.
SetupProc should match the following prototype:
typedef void Tcl_EventSetupProc(
ClientData clientData,
int flags);
The clientData argument will be the same as the clientData
argument to Tcl_CreateEventSource; it is typically used to
point to private information managed by the event source.
The flags argument will be the same as the flags
argument passed to Tcl_DoOneEvent except that it will never
by 0 (Tcl_DoOneEvent replaces 0 with TCL_ALL_EVENTS).
Flags 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 TCL_FILE_EVENTS
bit.
SetupProc's job is to provide information to
Tcl_WaitForEvent about how to wait for events.
It usually does this by calling Tcl_WatchFile or
Tcl_SetMaxBlockTime.
For example, setupProc can call Tcl_WatchFile to indicate
that Tcl_WaitForEvent should return when the conditions
given by the mask argument become true for the file given
by file.
The UNIX version of Tcl_WaitForEvent uses the
information passed to Tcl_WatchFile to set the file masks
for select, which it uses to wait for events.
If Tcl_WatchFile isn't called by any event sources then
Tcl_WaitForEvent will ignore files while waiting.
SetupProc can also invoke Tcl_SetMaxBlockTime to set an
upper bound on how long Tcl_WaitForEvent will block.
If no event source calls Tcl_SetMaxBlockTime then
Tcl_WaitForEvent will wait as long as necessary for an event
to occur; otherwise, it will only wait as long as the shortest
interval passed to Tcl_SetMaxBlockTime 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 timePtr argument to Tcl_WaitForEvent points to
a structure that describes a time interval in seconds and
microseconds:
typedef struct Tcl_Time {
long sec;
long usec;
} Tcl_Time;
The usec field should be less than 1000000.
Information provided to Tcl_WatchFile and Tcl_SetMaxBlockTime
is only used for the next call to Tcl_WaitForEvent; it is
discarded after Tcl_WaitForEvent 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.
In addition to the generic procedures Tcl_WatchFile and
Tcl_SetMaxBlockTime, other platform-specific procedures may
also be available for setupProc, if there is additional
information needed by Tcl_WaitForEvent on that platform.
The second procedure provided by each event source is its check
procedure, indicated by the checkProc argument to
Tcl_CreateEventSource. CheckProc must match the
following prototype:
typedef void Tcl_EventCheckProc(
ClientData clientData,
int flags);
The arguments to this procedure are the same as those for setupProc.
CheckProc is invoked by Tcl_DoOneEvent after it has waited
for events. Presumably at least one event source is now prepared to
queue an event. Tcl_DoOneEvent 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 Tcl_FileReady may be useful for some event
sources. It takes as arguments a file identifier file 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 Tcl_WaitForEvent.
Tcl_WaitForEvent only checks a file if Tcl_WatchFile was
called by at least one event source, so it is possible for
Tcl_FileReady to return 0 even if the file is ready.
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 Tcl_QueueEvent.
The evPtr 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 Tcl_Event, and the address of this structure is used when
communicating between the event source and the rest of the notifier.
A Tcl_Event has the following definition:
typedef struct Tcl_Event {
Tcl_EventProc *proc;
struct Tcl_Event *nextPtr;
};
The event source must fill in the proc field of
the event before calling Tcl_QueueEvent.
The nextPtr is used to link together the events in the queue
and should not be modified by the event source.
An event may be added to the queue at any of three positions, depending
on the position argument to Tcl_QueueEvent:
-
TCL_QUEUE_TAIL
-
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.
-
TCL_QUEUE_HEAD
-
Add the event at the front of the queue, so that it will be serviced
before all other queued events.
-
TCL_QUEUE_MARK
-
Add the event at the front of the queue, unless there are other
events at the front whose position is TCL_QUEUE_MARK; if so,
add the new event just after all other TCL_QUEUE_MARK events.
This value of position 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.
-
When it is time to handle an event from the queue (steps 1 and 5
above) Tcl_DoOneEvent will invoke the proc specified
in the first queued Tcl_Event structure.
Proc must match the following prototype:
typedef int Tcl_EventProc(
Tcl_Event *evPtr,
int flags);
The first argument to proc is a pointer to the event, which will
be the same as the first argument to the Tcl_QueueEvent call that
added the event to the queue.
The second argument to proc is the flags argument for the
current call to Tcl_DoOneEvent; this is used by the event source
to return immediately if its events are not relevant.
-
It is up to proc 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 Tcl_DoOneEvent
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
flags argument.
For example, the file event source will always return 0 if the
TCL_FILE_EVENTS bit isn't set in flags.
Another example of deferring events happens in Tk if
Tk_RestrictEvents has been invoked to defer certain kinds
of window events.
-
When proc returns 1, Tcl_DoOneEvent will remove the
event from the event queue and free its storage.
Note that the storage for an event must be allocated by
the event source (using Tcl_Alloc or the Tcl macro ckalloc)
before calling Tcl_QueueEvent, but it
will be freed by Tcl_DoOneEvent, not by the event source.
CREATING A NEW NOTIFIER
The notifier consists of all the procedures described in this
manual entry, plus Tcl_DoOneEvent and Tcl_Sleep.
Most of these procedures are generic, in that they are the
same for all platforms. However, four of the procedures are
platform-dependent: Tcl_WatchFile,
Tcl_FileReady, Tcl_WaitForEvent, and Tcl_Sleep.
To support a new platform, you must write new versions of these
procedures.
Tcl_WatchFile and Tcl_FileReady have already been
described previously in this document, and Tcl_Sleep
is described in its own manual entry.
Tcl_WaitForEvent 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 Tcl_WaitForEvent 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 Tcl_WatchFile.
The timePtr argument to Tcl_WaitForEvent gives
the maximum time to block for an event, based on calls to
Tcl_SetMaxBlockTime made by setup procedures and
on other information (such as the TCL_DONT_WAIT bit in flags).
Tcl_WaitForEvent uses information saved by Tcl_WatchFile,
plus the timePtr 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 Tcl_WatchFile nor
Tcl_SetMaxBlockTime has been called since the last call to
Tcl_WaitForEvent), so that the procedure would block forever,
then it returns immediately with a result of TCL_ERROR.
The easiest way to create a new notifier is to look at the code
for an existing notifier, such as the files generic/tclNotify.c
and unix/tclUnixNotfy.c.
KEYWORDS
block time, event notifier, event queue, event sources, file events
Last change: 7.5
[ tcl8.0a1 | tk8.0a1 | X-ref ]
Copyright © 1989-1994 The Regents of the University of California.
Copyright © 1994-1996 Sun Microsystems, Inc.