Previous section   Next section

Practical Programming in Tcl & Tk, Third Edition
By Brent B. Welch

Table of Contents
Chapter 16.  Event-Driven Programming

The fileevent Command

The fileevent command registers a procedure that is called when an I/O channel is ready for read or write events. For example, you can open a pipeline or network socket for reading, and then process the data from the pipeline or socket using a command registered with fileevent. The advantage of this approach is that your application can do other things, like update the user interface, while waiting for data from the pipeline or socket. Network servers use fileevent to manage connections to many clients. You can use fileevent on stdin and stdout, too. Using network sockets is described in Chapter 17.

The command registered with fileevent uses the regular Tcl commands to read or write data on the I/O channel. For example, if the pipeline generates line-oriented output, you should use gets to read a line of input. If you try and read more data than is available, your application may block waiting for more input. For this reason, you should read one line in your fileevent handler, assuming the data is line-oriented. If you know the pipeline will generate data in fixed-sized blocks, then you can use the read command to read one block.

The fconfigure command, which is described on page 221, can put a channel into nonblocking mode. This is not strictly necessary when using fileevent. The pros and cons of nonblocking I/O are discussed later.


End of file makes a channel readable.

You should check for end of file in your read handler because it will be called when end of file occurs. It is important to close the channel inside the handler because closing the channel automatically unregisters the handler. If you forget to close the channel, your read event handler will be called repeatedly.

Example 16-1 shows a read event handler. A pipeline is opened for reading and its command executes in the background. The Reader command is invoked when data is available on the pipe. When end of file is detected a variable is set, which signals the application waiting with vwait. Otherwise, a single line of input is read and processed. The vwait command is described on the next page. Example 22-1 on page 318 also uses fileevent to read from a pipeline.

Example 16-1 A read event file handler.
proc Reader { pipe } {
   global done
   if {[eof $pipe]} {
      catch {close $pipe}
      set done 1
   gets $pipe line
   # Process the line here...
set pipe [open "|some command"]
fileevent $pipe readable [list Reader $pipe]
vwait done

There can be at most one read handler and one write handler for an I/O channel. If you register a handler and one is already registered, then the old registration is removed. If you call fileevent without a command argument, it returns the currently registered command, or it returns the empty string if there is none. If you register the empty string, it deletes the current file handler. Table 16-2 summarizes the fileevent command.

Table 16-2. The fileevent command.
fileevent fileId readable ?command?Queries or registers command to be called when fileId is readable.
fileevent fileId writable ?command?Queries or registers command to be called when fileId is writable.

      Previous section   Next section