Specifying actions in event definitions
You can specify an action in an event type definition. This lets you call that action on an instance of the event, just as you would call a built-in method on some other type, such as calling the toString() method on the integer type.
When you define an action in an event, it behaves almost the same way as an action in a monitor or query. For example, an action in an event can
Set up event or stream listeners (only in a monitor)
Call other actions within that event
Access members of that event
In a monitor, but not in a query, an action in an event has an implicit self argument that refers to the event instance that the action was called on. The self argument behaves in the same way as the this argument in C++ or Java.
Example
For example, consider the following event type definition:
event Circle {
action area() returns float {
return 3.14159 * radius * radius;
}
action circumference() returns float {
return 2.0 * 3.14159 * self.radius;
}
float radius;
}
The specifications here of radius and self.radius are equivalent.
You can then write code that looks like this:
Circle c := Circle(4.0);
print "Circle area = " + c.area().toString();
print "Circle circumference = " + c.circumference().toString();
Of course, the output is as follows:
Circle area = 50.26544
Circle circumference = 25.13272
Behavior
The correlator never executes actions in events automatically. In an event, if you define an onload() action, the correlator does not treat it specially as it does when you define the onload() action in a monitor.
When you call an action in an event, the correlator executes the action in the monitor or query instance in which the call was made. In a monitor, if the action sets up any listeners, these listeners are in the context of this monitor instance. If this monitor instance dies, the listeners also die.
You can use plug-ins from within event actions. In the event definition, specify the import statement to give the plug-in an alias within the event. Specify the import statement in the same way that you specify it for a monitor or query. You use the plug-in alias to call functions on the plug-in in the same way as you use it for a monitor or query.
When you define an event, there are no ordering restrictions for the definition of fields, imports, or actions. You can define them in any order.
Spawning
From an action within an event, you can spawn to an action in the same event. The correlator spawns a monitor instance and executes the specified action on the event instance in the new monitor instance.
Note: | In a query, spawn and spawn...to statements are not needed and so they are not allowed. |
It is not possible to spawn from outside a particular event to an action that is a member of that particular event. Instead, spawn to an action that calls the action that is the event member. For example:
event E {
action spawntotarget() {
spawn target(); // legal
}
action target() {
log "Spawned "+self.toString();
}
}
monitor m {
action onload() {
E e;
spawn e.target(); // not legal
spawn calltarget(e); // legal
e.spawntotarget();
}
action calltarget(E e) {
e.target();
}
}
Be sure to follow the
spawn keyword with an
action name identifier. Actions spawned to must have no return value, as before. See also
Utilities for operating on monitors.
Restrictions
To summarize, when you define an action in an event, the following restrictions apply:
If the action contains an
on statement, you can coassign a matching event only to local variables. You cannot coassign a matching event to the event's fields nor to items outside the event or in the monitor.
In a monitor, if you declare an instance of an event that has an action member, you cannot specify a call from that action to an action that is defined in the monitor.
You cannot assign values to the implicit
self parameter, any more than you can assign to
this in Java.
The following event listener call syntax is not valid within event actions:
on A() foo;
Instead, specify this:
on A() foo();