www.gibmonks.com

  Previous section   Next section

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

Table of Contents
Chapter 16.  Event-Driven Programming


The fconfigure Command

The fconfigure command sets and queries several properties of I/O channels. The default settings for channels are suitable for most cases. If you do event-driven I/O you may want to set your channel into nonblocking mode. If you handle binary data, you should turn off end of line and character set translations. You can query the channel parameters like this:

fconfigure stdin
-blocking 1 -buffering none -buffersize 4096 -encoding
iso8859-1 -eofchar {}-translation lf

Table 16-3 summarizes the properties controlled by fconfigure. They are discussed in more detail below.

Table 16-3. I/O channel properties controlled by fconfigure.
-blockingBlocks until I/O channel is ready: 0 or 1.
-bufferingBuffer mode: none, line, or full.
-buffersizeNumber of characters in the buffer.
-eofcharSpecial end of file character. Control-z (\x1a) for DOS. Null otherwise.
-encodingThe character set encoding.
-errorReturns the last POSIX error message associated with a channel.
-translationEnd of line translation: auto, lf, cr, crlf, binary.
-modeSerial devices only. Format: baud,parity,data,stop
-peernameSockets only. IP address of remote host.
-peerportSockets only. Port number of remote host.

Nonblocking I/O

By default, I/O channels are blocking. A gets or read will wait until data is available before returning. A puts may also wait if the I/O channel is not ready to accept data. This behavior is all right if you are using disk files, which are essentially always ready. If you use pipelines or network sockets, however, the blocking behavior can hang up your application.

The fconfigure command can set a channel into nonblocking mode. A gets or read command may return immediately with no data. This occurs when there is no data available on a socket or pipeline. A puts to a nonblocking channel will accept all the data and buffer it internally. When the underlying device (i.e., a pipeline or socket) is ready, then Tcl automatically writes out the buffered data. Nonblocking channels are useful because your application can do something else while waiting for the I/O channel. You can also manage several nonblocking I/O channels at once. Nonblocking channels should be used with the fileevent command described earlier. The following command puts a channel into nonblocking mode:

fconfigure fileID -blocking 0

It is not strictly necessary to put a channel into nonblocking mode if you use fileevent. However, if the channel is in blocking mode, then it is still possible for the gets or read done by your fileevent procedure to block. For example, an I/O channel might have some data ready, but not a complete line. In this case, a gets would block, unless the channel is nonblocking. Perhaps the best motivation for a nonblocking channel is the buffering behavior of a nonblocking puts. You can even close a channel that has buffered data, and Tcl will automatically write out the buffers as the channel becomes ready. For these reasons, it is common to use a nonblocking channel with fileevent. Example 16-3 shows a fileevent handler for a nonblocking channel. As described above, the gets may not find a complete line, in which case it doesn't read anything and returns -1.

Example 16-3 A read event file handler for a nonblocking channel.
set pipe [open "|some command"]
fileevent $pipe readable [list Reader $pipe]
fconfigure $pipe -blocking 0
proc Reader { pipe } {
   global done
   if {[eof $pipe]} {
      catch {close $pipe}
      set done 1
      return
   }
   if {[gets $pipe line] < 0} {
      # We blocked anyway because only part of a line
      # was available for input
   } else {
      # Process one line
   }
}
vwait done

The fblocked Command

The fblocked command returns 1 if a channel does not have data ready. Normally the fileevent command takes care of waiting for data, so I have seen fblocked useful only in testing channel implementations.

Buffering

By default, Tcl buffers data, so I/O is more efficient. The underlying device is accessed less frequently, so there is less overhead. In some cases you may want data to be visible immediately and buffering gets in the way. The following turns off all buffering:

fconfigure fileID -buffering none

Full buffering means that output data is accumulated until a buffer fills; then a write is performed. For reading, Tcl attempts to read a whole buffer each time more data is needed. The read-ahead for buffering will not block. The -buffersize parameter controls the buffer size:

fconfigure fileID -buffering full -buffersize 8192

Line buffering is used by default on stdin and stdout. Each newline in an output channel causes a write operation. Read buffering is the same as full buffering. The following command turns on line buffering:

fconfigure fileID -buffering line

End of Line Translations

On UNIX, text lines end with a newline character (\n). On Macintosh they end with a carriage return (\r). On Windows they end with a carriage return, newline sequence (\r\n). Network sockets also use the carriage return, newline sequence. By default, Tcl accepts any of these, and the line terminator can even change within a channel. All of these different conventions are converted to the UNIX style so that once read, text lines always end with a newline character (\n). Both the read and gets commands do this conversion. By default, text lines are generated in the platform-native format during output.

The default behavior is almost always what you want, but you can control the translation with fconfigure. Table 16-4 shows settings for -translation:

Table 16-4. End of line translation modes.
binaryNo translation at all.
lfUNIX-style, which also means no translations.
crMacintosh style. On input, carriage returns are converted to newlines. On output, newlines are converted to carriage returns.
crlfWindows and Network style. On input, carriage return, newline is converted to a newline. On output, a newline is converted to a carriage return, newline.
autoThe default behavior. On input, all end of line conventions are converted to a newline. Output is in native format.

End of File Character

In DOS file systems, there may be a Control-z character (\x1a) at the end of a text file. By default, this character is ignored on the Windows platform if it occurs at the end of the file, and this character is output when you close the file. You can turn this off by specifying an empty string for the end of file character:

fconfigure fileID -eofchar {}

Serial Devices

The -mode attribute specifies the baud rate, parity mode, the number of data bits, and the number of stop bits:

set tty [open /dev/ttya]
fconfigure $tty -mode
=> 9600,0,8,2

If you need to set additional attributes of the serial channel, you will have to write a command in C that makes the system calls you need. If you are familiar with serial devices, you know there are quite a few possibilities!

Windows has some special device names that always connect you to the serial line devices when you use open. They are com1 through com8. The system console is named con. The null device is nul.

UNIX has names for serial devices in /dev. The serial devices are /dev/ttya, /dev/ttyb, and so on. The system console is /dev/console. The current terminal is /dev/tty. The null device is /dev/null.

Macintosh needs a special command to open serial devices. This is provided by a third-party extension that you can find at the Tcl Resource Center under:

http://www.scriptics.com/resource/software/extensions/macintosh

Character Set Encodings

Tcl automatically converts various character set encodings into Unicode internally. It cannot automatically detect the encoding for a file or network socket, however, so you need to use fconfigure -encoding if you are reading data that is not in the system's default encoding. Character set issues are explained in more detail in Chapter 15.

Configuring Read-Write Channels

If you have a channel that is used for both input and output, you can set the channel parameters independently for input and output. In this case, you can specify a two-element list for the parameter value. The first element is for the input side of the channel, and the second element is for the output side of the channel. If you specify only a single element, it applies to both input and output. For example, the following command forces output end of line translations to be crlf mode, leaves the input channel on automatic, and sets the buffer size for both input and output:

fconfigure pipe -translation {auto crlf}-buffersize 4096

      Previous section   Next section
    Top