HipHop Events

Introduction

In HipHop, events are the primary mean for exchanging information between different parts of a HipHop program, and from or to the outside world (i.e. Hop). Events can be used as a synchronization barrier, as a value aggregator and carrier, as a Boolean flag to choose a branch in a conditional, and more…

As events play a central role, a programmer shall understand what events are and how to use them. This understanding is the purpose of the present document.

Taxonomy

Events can be classified in different categories, depending on their properties. HipHop distinguish between pure and valued events, single and multiple emissions events, persistent and not persistent events, and status-less or not events. These four categories are not generally exclusive, resulting in 16 possible combinations [1].

Pure events does not carry any value. As such emitting a pure event with a value is an illegal operation.

Single events shall be emitted at most once per reaction (or input but not emitted). Emitting a single event more than once in a reaction throws a run-time exception. Multiple events can be emitted any number of times during a reaction. multiple valued events aggregates all emitted values depending in a user-specified procedure.

Persistent event keeps their previous status or value between instants. Such events exposes specific primitives to access the previous status or previous value of a given event.

status-less events does not have a status. They can be used as variables in a HipHop program.

Not all those combinations are implemented in HipHop. Please refer to the implementation section for details.

[1]Actually less than 16, status-less pure events are of non interest. See the implementation status table.

Operations

An event may carry several types of information, but only two are exposed to the programmer: the event status and its value. An event may be persistent between reactions. There are two means to update events: using hiphop-input! or with the emit& statement.

Status

The status is a Boolean value telling us if a given event is present or absent. An event which is present has been emitted during the current reaction. An event which is absent has not (and will not) be emitted during the current reaction. Here, will not means that the absent status is known before the end of the reaction, allowing HipHop programs to instantaneously react to the absence of an event [2]. An event is considered present in a reaction iff it has been input after the beginning of the precedent reaction and before the beginning of the considered reaction, or if an emit& statement for this peculiar event has been executed.

The presence status is accessed through the now& primitive. A persistent event previous status is accessed using pre& instead of now&.

[2]This is an essential difference compared to some other reactive models where reaction to the absence is done at the next reaction.

Values

An event may carry one or several values, such an event is said to be a valued event. HipHop distinguishes two types of valued event. Single valued events, whose value is unique and immutable during a reaction. Combined valued events, whom value is an aggregation of all values emitted during a reaction.

Due to HipHop semantics, an event's value shall only be accessed when all emitters for that peculiar event have either been executed or are known to be unreachable in the current reaction.

The value is accessed using val&. A persistent event previous value is accessed using preval&. See Event status and value Section below for more details.

Implementation

Status

The following table summarizes the different possible combinations of event properties, and which ones are implemented, implementable or not implementable.

Status Valued Single Persistent Implementation provider
false false any any None of interest
false true false false Not supported
false true false true Not supported
false true true false Not supported
false true true true Not supported
true false false false (class HipHopEventPureEvent)
true false false true (class HipHopEventPureEvent)
true false true false No default implementation
true false true true No default implementation
true true false false Ok (user-defined)
true true false true Ok (user-defined)
true true true false Ok (user-defined)
true true true true Ok (user-defined)

Type hierarchy and methods

HipHop events are Hop objects. The Hop object model does not allow multiple inheritance, as such the type hierarchy only distinguishes between kinds of valued events. The other event's properties, detailed in Section Taxonomy, are attributes of Hop objects.

::%HipHopEvent (abstract)

All events are instances of the abstract class ::%HipHopEvent. The constructor's name is hiphop-event-init!. The default constructor does nothing.

The %HipHopEvent class declares the following fields:

Field name Type Default value Description
name string (gensym) Name the event, for debugging purposes
single? Boolean false Is the event single?
persistent? Boolean false Is the event persistent?
status? Boolean true Does the event has a status?

The %HipHopEvent class defines the following generic functions:

(generic hiphop-event-reset! e::%HipHopEvent)
Called before each reaction to reset an event state. This procedure is also called when newly-entering a local& declaration.
(generic hiphop-event-emit! e::%HipHopEvent)
Called each time an emit& statement is executed.
(generic hiphop-event-present? e::%HipHopEvent)
Called by now&
(generic hiphop-event-previously-present? e::%HipHopEvent)
Called by pre&

Pure events

Pure events are instances of the ::HipHopEventPure class. This class is provided by the HipHop library and is directly available to use.

The HipHopEventPure type does not override any of the generic functions described above. A programmer is free to override these functions.

::%HipHopEventValued (abstract)

Valued event classes shall inherit from HipHopEventValued. This type defines new generics for accessing and mutating an event's value.

The %HipHopEventValued class declares the following generic functions for emitting an event:

(generic hiphop-event-compose! ::%HipHopEventValued ::obj)
(generic hiphop-event-compose-1! ::%HipHopEventValued ::obj ::obj)
(generic hiphop-event-compose-2! ::%HipHopEventValued ::obj ::obj ::obj)
(generic hiphop-event-compose-3! ::%HipHopEventValued ::obj ::obj ::obj ::obj)
(generic hiphop-event-compose-n! ::%HipHopEventValued . args)

Those generics are called when a value specified by emit& or hiphop-input! has to be emitted in an event. The number indicates the number of extra arguments that are passed along with the call.

Symmetrically, the following generics enables retrieving an event's value:

(generic hiphop-event-value::obj ::%HipHopEventValued)
(generic hiphop-event-value-1::obj ::%HipHopEventValued ::obj)
(generic hiphop-event-value-2::obj ::%HipHopEventValued ::obj ::obj)
(generic hiphop-event-value-3::obj ::%HipHopEventValued ::obj ::obj ::obj)
(generic hiphop-event-value-n::obj ::%HipHopEventValued . args)

For persistent events, the following generics enables retrieving the previous value of an event:

(generic hiphop-event-previous-value::obj ::%HipHopEventValued)
(generic hiphop-event-previous-value-1::obj ::%HipHopEventValued ::obj)
(generic hiphop-event-previous-value-2::obj ::%HipHopEventValued ::obj ::obj)
(generic hiphop-event-previous-value-3::obj ::%HipHopEventValued ::obj ::obj ::obj)
(generic hiphop-event-previous-value-n::obj ::%HipHopEventValued . args)

All the above generic default implementation is void. A programmer which wishes to use them must defines the method he/she will use.

Event emissions

The Operations Section has presented the user API to emit events. Emissions are realized through emit& and hiphop-input!.

The emit& statement calls the method hiphop-event-emit! each time it is executed. The default method marks the event present and increments the emitted counter. It is highly discouraged to override this method without issuing a call to call-next-method, as it may break HipHop semantics, and induce an unspecified behavior.

The emit& statement accepts several arguments after the event argument. This feature enables the emission of a value for the given event. The general syntax of emit& is recalled below:

(emit& <event> [<val1> [<val2> [... <valn>]]])

where <event> shall be an instance of ::%HipHopEvent if no <val> is specified, or an instance of ::%HipHopEventValued otherwise.

If at least one <val> argument is specified, the associated hiphop-event-compose…! method is invoked when the emit& statement is executed.

Event status and value

Event stratus is retrieved using the API syntax now&. Use pre& to retrieve a persistent event's presence at the previous instant. The syntax is rather simple, here <event> shall be an instance of ::%HipHopEvent:

(now& <event>)
(pre& <event>)

Event value is retrived using the API syntax val& (or preval& for the previous value of a persistent event). Both have the same syntax:

(val& <event> [<val1> [... <valn>]])
(preval& <event> [<val1> [... <valn>]])

where <event> shall be an instance of ::%HipHopEventValued, and each <val> are host expressions. When the val& form (resp. preval&) is executed, in calls the associated hiphop-event-value… (resp. hiphop-event-previous-value…), depending on the number of extra arguments passed to the val& or preval&.

Provided events classes

The HipHop distribution provides several classes implementing the interface described above.

Pure events were rapidly introduced in Section Pure Events. HipHop also provides single-valued events, through the class ::HipHopEventValued (note the absence of the % sign before the name). Multi-sets are provided through HipHopEventList. Binary numerical operations can be handled by HipHopEventNum. Last, one dimensional event values are provided as hashtable via the class HipHopEventHash.

HipHopEventPure

The HipHopEventPure class merely derives %HipHopEvent. It adds no fields, nor override any of the default generics. Pure Events may be created persistent, but they cannot be created as single.

Single-valued events

Single-valued events are single. Setting the single? attribute to false is silently ignored. As such, only one valued emission is allowed per instant. Single-valued event may be declared as persistent, as the provided implementation supports it.

The methods hiphop-event-compose-*, hiphop-event-value-* are not overrided in their extra-argument versions.

HipHopEventNum

HipHopEventNum events are multi-valued events which use a binary composition function. The composition function is expected to be associative and commutative. Those events have an initial value which must be compatible with the operator procedure.

For instance, to declare a numeric event which sums up all its emitted values during an instant, one can write the following code:

(let ((addition-event
         (instantiate::HipHopEventNum
            (name "An optional name")
            (init 0)
            (op +)))))

HipHopEventList

List is an obvious data type for scheme programmer. List can also used for dynamically extended forms such as genpar&. HipHop provides the programmer with a predefined event class that aggregates all its emitted values during one instant in a list.

Semantic note: the order of the values in the list is of no meaning. The HipHop semantics tells you that the list data structure used to store the values must be mathematically seen as a multi-set.

Instantiation of HipHopEventList objects does not require any extra parameter.

HipHopEventHash

Hashtable events use an internal hashtable to store a collection valued-emission, using a key to index each value. The provided implementation supports the persistent? attribute. However, the single? attribute is ignored, as by construction, hashtable events may store any number of value.

The provided implementation overrides hiphop-event-compose-1! and hiphop-event-value-1 which are used to store or retrive a value using a specified key in the hashtable. For convenienve purposes, the implementation also overrides hiphop-event-value which build a list of all key-value pairs.


Return to Top
Page last modified Sat May 25 10:22:55 2013.