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


next up previous contents index
Next: await Statement Up: Events Previous: Send Expressions

Subsections



whenever Statement

You specify what to do when an agent generates an event using a whenever statement. As discussed above and in § 5.10.2, these look like:

whenever event1, event2, ... do statement
where at least one event must be listed.

When executed, Glish evaluates the event specifiers listed after the whenever keyword, and subsequently whenever any of those events are generated Glish executes statement. Thus a whenever statement can refer to several different events generated by several different agents.


Event Syntax

You can specify an event for a whenever statement in one of three forms:

expr -> name

expr1 -> [ expr2 ]

expr -> *
As when sending events (See § 7.4, page [*]), Glish evaluates the expression to the left of the -> operator to determine which agent you're talking about. With the first form, name then specifies the name of the event of interest. With the second form, Glish evaluates expr2 to produce a string value. Each element of that value then designates an event produced by the agent. For example,
    whenever a->["foo bar bletch"] do
        print $value
prints the value of each foo, bar, and bletch event generated by the agent a; it is equivalent to:
    whenever a->foo, a->bar, a->bletch do
        print $value
The third form indicates interest in every event generated by the agent. For example,
    whenever a->* do
        print $value
prints the value of every event a generates.

Execution of whenever

When a whenever is executed, each of the event's is evaluated to see which events of which agents they designate. Whenever any of those events subsequently occurs, statement is executed. We refer to statement as the body of the whenever statement.

As noted in § 6.6.2, page [*], if a function executes a whenever and then exits, its variables persist after the function call finishes, and the whenever body can access and modify the variables. For example, a call to:

    func report_foo(x)
        {
        y := 3
        whenever x->foo do
            {
            print y
            y +:= 1
            }
        y := 7
        }
prints 7 the first time x generates a foo event, 8 the next time, and so on.

Glish does not define the order of execution of two or more whenever statements that match the same event.

An important point is that each time you execute a whenever, a connection is made between the arrival of the given events and executing the whenever's body. If you called report_foo twice with the same x argument, then the first time x generated a foo event Glish would print 7 twice, the second time 8 twice, and so on. Furthermore, if x generated a foo event between the first and second calls to report_foo then the next time it generated a foo event Glish would print 8 and 7 (perhaps in the opposite order), and the next time 9 and 8.

Similarly, a single call to:

    func announce_bar(x)
        {
        for ( i in 1:3 )
            whenever x->bar do
                print "x did bar"
        }
will result in Glish printing "x did bar" three times every time x generates a bar event.

A final note: when Glish receives an event it only executes the corresponding whenever bodies at well-defined times (in particular, not when it is in the middle of executing any other statements). (See § 13.1.2, page [*], for a complete discussion of how Glish proceeds in executing programs and processing events.)


$agent, $name, and $value

Each time Glish receives an event it sets three special variables: $agent is the agent associated with the event, $name the event's name, and $value the event's value. For example, the body of the following whenever

    whenever x->foo do
        print $name
always prints foo, since a foo event is the only possible event that can result in the body executing. The following prints the value of each foo event generated by x or y, but only prints the name of the event if y generated it:
    whenever x->foo, y->foo do
        {
        print $value
        if ( $agent == y )
            print $name
        }
Because agent values are also records (See § 7.2.2, page [*]), after Glish receives an event the following is always true:
    $agent[$name] == $value
Here $name provides a string index for the agent's record, designating the field with the same name as the new event.

$name is particularly useful in conjunction with the * event designator (See § 7.5.1, page [*]). For example, the following whenever ``relays" every event generated by x to y, with the same name and value:

    whenever x->* do
        y->[$name]( $value )
Glish provides a number of functions for doing this sort of relaying. (See § 10.9, page [*].)


activate and deactivate Statements

Ordinarily, once a whenever statement is executed, it remains active. That is, whenever an event arrives corresponding to one designated when the statement was executed, Glish executes the body of the whenever statement. Sometimes, though, other events may occur leading you to want to deactivate a whenever statement so its body no longer executes. Glish provides a deactivate statement for turning off execution of a whenever's body, and a corresponding activate statement for turning it back on. The simplest form of these statements is simply:

activate

deactivate
These indicate that the ``currently executing'' whenever body (or the most-recently executed one, if none is current) should be activated or deactivated, respectively. For example,
    count := 0
    whenever a->foo do
        {
        do_stuff()
        count +:= 1
        if ( count >= 5 )
            deactivate
        }
will call do_stuff() upon receiving a's first 5 foo events, but then will quietly ignore the remainder.

You can also give the activate and deactivate statements an optional argument specify which whenever statement(s) to affect:

activate expr

deactivate expr
Here expr must evaluate to an integer (possibly a vector) built out of values returned using the current_whenever(), last_whenever_executed(), and whenever_stmts() functions (See § 10.9, page [*]). The corresponding whenever bodies are then activated or deactivated. For example, the following only responds to a's foo events (by calling do_foo()) if one or more intervening bar events have been received since the last foo event:
    whenever a->foo do
        {
        do_foo()
        deactivate  # wait for bar
        }

    a_foo := last_whenever_executed()

    whenever a->bar do
        {
        do_bar()
        activate a_foo
        }
The state of a whenever statement can be checked with the builtin function whenever_active() (See § 10.9, page [*]). Given an index, it will return T only if the statement is currently active.

See the discussion of the active_agents() function (§ 10.9, page [*]) for an example of using deactivate with a vector argument.


next up previous contents index
Next: await Statement Up: Events Previous: Send Expressions   Contents   Index
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