This method is used to create file event handlers. A file event handler is a binding between a file and a callback, such that the callbackis invoked whenever the file becomes readable or writable. File event handlers are most commonly used to allow data to be received from a child process on an event-driven basis, so that the receiver can continue to interact with the user while waiting for the data to arrive. If an application invokes perl file operations such as <> or read when there is no input data available, the process will block; until the input data arrives, it will not be able to service other events, so it will appear to the user to ``freeze up''. With fileevent, the process can tell when data is present and only do operations when they won't block.
The fileId argument to fileevent refers to an open file; any normal perl representaion of a file can be used such as STDIN, STDOUT, STDERR, or previously opened FileHandle objects or \*name "globs". If the callback argument is specified, then fileevent creates a new event handler: callback will be evaluated whenever the file becomes readable or writable (depending on the argument to fileevent). In this case fileevent returns an empty string. The readable and writable event handlers for a file are independent, and may be created and deleted separately. However, there may be at most one readable and one writable handler for a file at a given time. If fileevent is called when the specified handler already exists, the new callback replaces the old one.
If the callback argument is not specified, fileevent
returns the current callback for fileId, or an empty string
if there is none.
If the callback argument is specified as an empty string
then the event handler is deleted, so that no callback will be invoked.
The file event handler is not deleted automatically whenever
its file is closed as perl does not provide appropriate hooks, the perl/Tk
code will detect some cases and delete the handler, but it is good practice
to explcitly use
$widget->fileevent(fileId,'readable' => '');
to remove the handler when file is closed.
The file event handler is deleted automatically if the MainWindow
associated with $widget is destroyed.
A file is considered to be readable on same basis as the system's select() (or poll()). This typically means that a "tty" has a whole line readable but same is not true of "pipes" as pipe's buffer may fill before the newline. At least one character or an end-of-file or error condition is present. Perl's sysread with specifying a single character is always safe, other mechanisms are application dependant. It is important for callback to check for error and end-of-file conditions and handle them appropriately; for example, if there is no special check for end-of-file, an infinite loop may occur where callback reads no data, returns, and is immediately invoked again.
When using fileevent for event-driven I/O, it's important to read the file in the same units that are written from the other end. For example, suppose that you are using fileevent to read data generated by a child process. If the child process is writing whole lines, then you could use <> (in a scalar context) to read those lines. If the child generates one line at a time then you shouldn't make more than a single call to <> or use it in an array context in callback: the first call may consume all the available data, so the second call may block. You can also use sysread to read the child's data, but only if you know how many bytes the child is writing at a time: if you try to read more bytes than the child has written, the sysread call will block.
A file is considered to be writable on same basis as the system's select() (or poll()). Typically this means at least one byte of data can be written to the file without blocking, or an error condition is present. Write handlers are probably not very useful without additional support, although syswrite one character at a time is possible. The print command is dangerous since it can write more than one byte at a time and may thus block. What is really needed is a non-blocking form of write that saves any data that couldn't be written to the file.
The callback for a file event is executed in same perl context that MainLoop was invoked. If an error occurs while executing the callback then the Tk::Error mechanism is used to report the error. In addition, the file event handler is deleted if it ever "dies"; this is done in order to prevent infinite loops due to buggy handlers.
Perl's POSIX module provides a number of calls which would be useful with filevent, however core Tk code for filevent assumes existance of stdio style FILE * which POSIX module does not provide.
The Tk::IO class attempts to address the several of the above issues by providing a higher level interface - including using non-blocking read/write, and some buffering. This level of interface is still evolving, but should stabilize now perl's FileHandle objects have been cleaned up. A completely clean interface is not possible without additional changes to perl internals.
As of Tcl/Tk4.1b1 the Tk mechanism used to implement fileevent migrates into Tcl, and is changed slightly (to work better on non-UNIX machines). The impact of these changes on future perl/Tk releases has not let been established.
fileevent is based on the addinput command created by Mark Diekhans.