Tcl_CreateEventSource(Tcl Library ProceduTcl_CreateEventSource(3)_________________________________________________________________NAME
Tcl_CreateEventSource, Tcl_DeleteEventSource, Tcl_Watch-
File, 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 pre-
pare 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 setup-
Proc and
checkProc.
Tcl_File file (in) Generic file
handle as
returned by
Tcl 7.5 1
Tcl_CreateEventSource(Tcl Library ProceduTcl_CreateEventSource(3)
Tcl_GetFile.
int mask (in) Indicates the
events of
interest on
file: an
OR'ed combina-
tion of
TCL_READABLE,
TCL_WRITABLE,
and TCL_EXCEP-
TION.
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_Wait-
ForEvent 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 7.5 2
Tcl_CreateEventSource(Tcl Library ProceduTcl_CreateEventSource(3)
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:
[1] Event sources: these represent the ways in which
events can be generated. For example, there is a
timer event source that implements the Tcl_Create-
TimerHandler 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.
[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.
[3] 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:
[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.
[2] Prepare to block for an event. To do this,
Tcl 7.5 3
Tcl_CreateEventSource(Tcl Library ProceduTcl_CreateEventSource(3)
Tcl_DoOneEvent invokes a setup procedure in each
event source. The event source will call proce-
dures like Tcl_WatchFile and Tcl_SetMaxBlockTime to
indicate what low-level events to look for in
Tcl_WaitForEvent.
[3] Call Tcl_WaitForEvent. This procedure is imple-
mented differently on different platforms; it
waits for an event to occur, based on the informa-
tion 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 becom-
ing readable or the interval given by timePtr
expiring. If there are no events for Tcl_Wait-
ForEvent to wait for, so that it would block for-
ever, then it returns immediately and
Tcl_DoOneEvent returns 0.
[4] 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.
[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.
[6] See if there are idle callbacks pending. If so,
invoke all of them and return.
[7] 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,
Tcl 7.5 4
Tcl_CreateEventSource(Tcl Library ProceduTcl_CreateEventSource(3)
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_Wait-
ForEvent 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_Wait-
ForEvent will wait as long as necessary for an event to
occur; otherwise, it will only wait as long as the short-
est 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 7.5 5
Tcl_CreateEventSource(Tcl Library ProceduTcl_CreateEventSource(3)
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 addi-
tional 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 condi-
tions 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;
};
Tcl 7.5 6
Tcl_CreateEventSource(Tcl Library ProceduTcl_CreateEventSource(3)
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 posi-
tions, 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 rele-
vant.
It is up to proc to handle the event, typically by invok-
ing 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
Tcl 7.5 7
Tcl_CreateEventSource(Tcl Library ProceduTcl_CreateEventSource(3)
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 plat-
form, 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 ``inter-
esting'' 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_Set-
MaxBlockTime made by setup procedures and on other infor-
mation (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 immedi-
ately 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.
Tcl 7.5 8
Tcl_CreateEventSource(Tcl Library ProceduTcl_CreateEventSource(3)KEYWORDS
block time, event notifier, event queue, event sources,
file events
Tcl 7.5 9