next up previous contents index
Next: Point-to-Point Communication Up: Events Previous: whenever Statement

await Statement

 

  As discussed in § 5.10.2, the await statements comes in three forms:

await eventtex2html_wrap_inline15496, eventtex2html_wrap_inline15498, tex2html_wrap_inline15512

await only eventtex2html_wrap_inline15496, eventtex2html_wrap_inline15498, tex2html_wrap_inline15512

await only eventtex2html_wrap_inline15496, eventtex2html_wrap_inline15498, tex2html_wrap_inline15512 except eventtex2html_wrap_inline15496, eventtex2html_wrap_inline15498, tex2html_wrap_inline15512

In each of these forms, event designates an event just like in a whenever statement.

Usage

An await statement instructs Glish to wait for one of the listed events to occur. Glish pauses program execution until this happens. Without the only keyword, Glish will still process incoming events by executing their corresponding whenever bodies. This style of await can be used to effect synchronous communication with an agent. For example, suppose that c refers to a client that when sent a compute request performs some computation and generates a compute_done event when finished. If you want to tell c's client to do its computation and wait for the result, you could do:

    c->compute()
    await c->compute_done

    # at this point, c is done
    # with its computation
After an await completes, $agent, $name, and $value correspond to the event that caused the await to finish. In the above example, $agent will be c, $name will be "compute_done", and $value will be the value of the compute_done event. In general, though, this is probably better written as:
    result := c->compute()
This version is more concise and more efficient.

  If you use the only keyword then while Glish is waiting for one of the listed events, no intervening events it receives will be processed. Instead, these events are ``dropped"; it is as though they had never occurred, though Glish generate a warning message concerning each dropped event.

await only is meant for use as a ``hold-point", to freeze the effective execution of a Glish program until some seminal event occurs. For example, suppose that when key_program generates a panic event that it is vital to suspend execution of the Glish program and its clients until the current program state can be archived by the archiver client. You might program this using:  

    whenever key_program->panic do
        {
        print "panic, doing archive snapshot"
        archiver->do_archive
        await only archiver->archive_done
        }

Sometimes during such an await only there are a few events that if they arrive still must be processed. Glish provides for   this case with the await only tex2html_wrap_inline15512 except statement. If in the above example we also had a high_priority client that had to continue even during the archiving, we could have used:  

    whenever key_program->panic do
        {
        print "panic, doing archive snapshot"
        archiver->do_archive
        await only
                archiver->archive_done except
                high_priority->*
        }
Similarly, we could restrict which of high_priority's events were processed during archiving by replacing the * event name with a specific event name or list of names:
    whenever key_program->panic do
        {
        print "panic, doing archive snapshot"
        archiver->do_archive
        await only
                archiver->archive_done except
                high_priority->interrupt
        }

Interaction with whenever

 

Since in general when executing an await other events may be processed, leading to the execution of the body of whenever statements, the question arises ``What happens if one of those whenever bodies itself executes an await?" We call   such an await within another await a nested await.

Only the most recently executed nested await is active, i.e. execution is stopped until that await gets its event. But all of the awaits that are queued up will get their value in the order that they started waiting. Lets look at an example:  

    c1 := client("c1")
    c2 := client("c2")

    whenever c1->ready do
        {
        c2->doit()
        await c2->done
        }

    whenever c2->ready do
        {
        c1->doit()
        await c1->done
        }
if c1 generates a ready event we will send a doit event to c2 and then enter an await waiting for c2 to generate done. If c2 then first generates ready prior to generating done then we will execute the second whenever clause, resulting in sending a doit event to c1 and then a nested await as we wait for c1 to generate done.

If c1 now generates done then we go back to waiting for c2 to generate done. But what happens if c2 generates a done event before c1? In this case, the done event from c2 is held for the await pending for c2 until a done event is received from c1. So where awaits are concerned, the events are processed in the order forced by the script rather than the order the events were received.

There can even be cases where two awaits are waiting for the same event from the same client. In this case, the first await gets the first event coming from the client. The second await must continue to wait for the next event of the specified type. This is typically what is desired because the agent probably processes the first event it recieves and generates a result before starting on the second event.    


next up previous contents index
Next: Point-to-Point Communication Up: Events Previous: whenever Statement

Thu Nov 13 16:44:05 EST 1997