Getting Started Documentation Glish Learn More Programming Contact Us
Version 1.9 Build 1556
News FAQ
Search Home


next up previous
Next: What now? Up: NOTE 195 Getting Started with Glish for AIPS++ Previous: Printing

Clients, Events, and Agents

From a software designer's point of view, the important part of glish is its ability to link to any number of independent processes running anywhere on a computer network. To glish these independent processes are seen as ``clients'', but the client-server distinction is ambiguous since services can flow either way. Communication between glish and its clients is by way of ``events'', rather analogous to hardware interrupts but with the added feature that events can carry any amount of data to or from a client.

As an AIPS++ user you may seldom encounter the use of events in your glish programming. Events are considerably different in concept from usual linear scientific programming. Hence, they are usually wrapped in more familiar function calls to avoid the need to learn events to use the services of AIPS++ clients. In fact, in the examples above we have used a number of clients, including the table browser and the plot client, without necessarily being aware of events passing back and forth. It's not that clients and events are all that obscure. It is just that they are one more concept to learn that might not be of any direct interest.

Clients can do anything that a normal computer program can do from performing FFT's to driving a telescope to position. Most of the application-specific facilities of AIPS++ are in the clients that glish initiates.

To see how the events work try the following commands associated with the Tk widgets attached to glish.

- mp := pgplotter()
- fm := frame()
- b1 := button(fm, 'plot')
- whenever b1->press do {
-  mp.eras()
-  mp.plotxy([1:100],sin(as_float(1:100) / 20.0), title='Button plot')
- }

The first statement puts a small window frame on the screen. The second puts a button labeled 'plot' in the window. In the whenever statement, ``press'' is the name of an event sent by the Tk widgets client when the button is pressed with the mouse. The statements within the whenever block are executed when the 'press' event is received. Try pressing the button.

Clients are started from glish with the client() function. A more complex example than the button client might be a hypothetical FFT engine. Let's say that we have an executable file on disk, called ``fft_engine'', that performs Fourier transforms and knows how to send and receive glish events. Start it up with

- fft := client('fft_engine', host='arcturus')

The host argument is not needed if ``fft_engine'' is on the same machine that is running glish. The variable, fft, is of a special type called an agent.

Suppose that the documentation for fft_engine says that it recognizes an event called ``do_fft'', and , when the FFT is done, fft_engine will send an event called ``fft_done'' with a new array of transformed data. First, set up to receive the ``fft_done'' event and do something with it. Then send the fft request with the data array. Probably in a script called 'fft.g' we'd have

fft := client('fft_engine')
whenever fft->fft_done do {
   mp.eras()
   mp.plotxy([1:len($value)], $value, title='FFT Result')
}

Then from the command line do the following:

- include 'fft.g'
- data := sin(as_float(1:128) / 3.0)
- send fft->do_fft(data)
- await fft->fft_done

In this case we have elected to wait for the ``fft_done'' event to return and be processed, but we could have continued to issue glish statements for other purposes. The FFT result would be returned and plotted whenever the fft_engine client was finished with it.

The parameter, $value, is a special one associated with events. It contains the event's data and can be anything from a single number or string to a very complicated record with arrays and other records as members. Normally, glish and the client know what to expect in $value, but some flexibility of contents and data types can be supported with the is_xxxx() test functions.

A fully implemented glish client is written at least partly in C++ using the classes that support events and glish data structures. However, existing programs may be turned into simple clients using standard input and output ASCII data as event values. Also, clients may be written in the glish language, but there are fewer reasons for doing it this way.

The standard-in, standard-out client is created by the shell() function rather than the client() function. A one-time communication with a client program is simply the UNIX command as a string argument to shell().

- file_list := shell('ls *.g')

The variable, file_list, is then an array of strings, one string for each file name that ends with ``.g'' in the directory.

If the program can handle more than one exchange of data by way of UNIX pipes, it may be started and communicated to with events. The startup glish code looks something like

a := shell('my_prog', async=T)
whenever a->stdout do {
    print $value
}
whenever a->stderr do {
    print 'Error !', $value
}

The async=T parameter assignment causes the shell() function to return an agent type quantity instead of a string. The data events that can be sent by the client started with the shell command are called ``stdout'', and ``stderr'' and their $value is always a string. The two events recognized by a shell client are ``stdin'', whose argument must always be a string, and ``EOF''. Hence, an event sent to ``my_prog'' is, for example,

- send a->stdin('23.876 14.999')

To avoid having an event arrive from a new client before its associated whenever statements are set up, put the client() or shell() function calls and the whenever statement in the same script file, and run them together in the script. Glish guarantees that events are held until the full script file is read.


next up previous
Next: What now? Up: NOTE 195 Getting Started with Glish for AIPS++ Previous: Printing
Please send questions or comments about AIPS++ to aips2-request@nrao.edu.
Copyright © 1995-2000 Associated Universities Inc., Washington, D.C.

Return to AIPS++ Home Page
2006-10-15