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

Overview of Agent Interaction

 

As noted earlier, all interaction between the Glish interpreter and agents happens by sending and receiving events. This separation encourages isolation of the system components. This isolation makes the components more reusable because they have a well defined interface. All of this means that these agents can be knitted together by the Glish interpreter in unanticipated ways. Each agent becomes a pluggable component of the system.

Sending Events

In general, events are sent to agents like:

    demo := client("my_demo")
    demo->foo( [1, 4, 6] )
In this example, the agent demo is a process running on the local operating system. The client function is used to create such agents (see § 7.8, page gif). Once the demo agent is created, a foo event is sent to demo with a value of [1, 4, 6].

In this case, no result was expected from demo as a result of the foo event. If the event had been sent in a different context, the interpreter would have waited for a result from the agent. For example (continuing the previous example):

    if ( demo->bar( 1.71 ) )
        print "true from demo"
In this case, because of the context in which the event is sent the interpreter waits for a result from demo, and output is generated only if the result resolves to T. When the client process, ``my_demo'', receives the event, it is notified that a result is expected (see § 13.2, page gif).

Sending an event is in many ways similar to making a function call. Values can be obtained from an agent:

    v := database->get_voltage( 1:10 )
This example sends a get_voltage event to the agent database with a value of 1:10, waits for database to generate an event in response, and assigns the value of that response to v. More than one value can be sent to an agent:
    database->insert( "integral", 2.9812 )
This example sends database an event with two values, the string "integral" and 2.9812. Values sent to an agent can also be named:
    c := 0
    while ( v := database->get( table = "A", offset = c +:= 1 ) )
        print v
This example repeatedly sends get events to the client with the ``parameter'' table equal to "A" and offset equal to c. c is incremented each time through the loop before the event is sent. The loop only stops when demo returns a value which resolves to F. Passing these multi-element event values is equivalent to passing a single-valued event where the value is a record. This last example, for instance, is equivalent to:
    c := 0
    while ( v := database->get( [table = "A", offset = c +:= 1] ) )
        print v
Finally, if no values are are specified the event values is the boolean scalar F. Here:
    print database->version( )
the value which accompanies the event version is F.

It is important to note that the context affects the event that goes to the agent based on whether a result is required or not. In general, the only time when a result is not expected is when the expression which sends the event is on a line by itself. It is the difference between:

    print any_client->event( 1:10 )
and
    any_client->event( 1:10 )
In the first case, a result is needed so the event type that the client receives indicates that it needs to generate a result event. In the second case, no result is required.

Processing Asynchronous Events

 

In the cases above, events were sent to agents, but the agents only generated an event when it was required by events received by the agent. This happened in a request/reply sort of dialog between the interpreter and an agent. Agents can, however, generate events at anytime, and Glish has language constructs to deal with these events. These events can occur at anytime regardless of what the Glish interpreter is busy doing.

Suppose that a is an agent-valued variable. In a Glish program you can process events that a generates   using a whenever statement. Once executed,

    a := client("demo")
    whenever a->bar do
        print "got a bar event"
will print "got a bar event" every time the demo process generates a bar event.

The value of the most recently received event is kept in a   special variable $value:

    whenever a->bar do
        print "got a bar event =", $value
will display the value of each bar event that a generates.

$value can be used in expressions just like other variables. Here's a fragment that only prints out the value of the bar event if it's an integer vector with 3 elements:

    whenever a->bar do
        if ( is_integer($value) && len($value) == 3 )
            print "got a bar event =", $value
This fragment prints every other bar event:
    count := 0
    whenever a->bar do
        {
        count +:= 1
        if ( count % 2 == 1 )
            print $value
        }
Event values can be stored in variables and record fields just like any other value:
    last_bar := "none"
    whenever a->bar do
        {
        print "got a bar event =", $value
        print "the previous bar event was", last_bar
        last_bar := $value
        }
will print out both the value of each of a's bar events and the value the event had the previous time it was received. The output from this program might look something like:
    got a bar event = 3
    the previous bar event was none
    got a bar event = hello there
    the previous bar event was 3
    got a bar event = 1 4 7
    the previous bar event was hello there
and so on.

Furthermore, each agent value is also a record (see § 7.2.2, page gif). Whenever the agent generates an event, a field in the record with that event's name is set to the event's value. This means that:

    whenever a->bar do
        print "got a bar event =", $value
is equivalent to
    whenever a->bar do
        print "got a bar event =", a.bar
and that it's easy to refer to past events with different names:
    whenever a->bar do
        {
        print "got a bar event =", a.bar
        print "the last foo event was", a.foo
        }
 


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

Thu Nov 13 16:44:05 EST 1997