3 The Event Module
Events in Ensemble are used for intra-stack communication, as opposed
to inter-stack communication, for which messages are used. Currently, the
event module is the only Ensemble-specific module that all layers use.
Events contain a well-known set of fields which all layers use for
communicating between themselves using a common event protocol.
Learning this protocol is one of the harder parts of understanding Ensemble.
In this section we describe the operations supported for events; in
section 4 we describe the meaning of the various event
types and their fields.
We repeatedly refer the reader to the source code of the event module source
files, both type/event.mli and type/event.ml. This is done to
ensure that information in this documentation does not fall out of date due to
small changes in the event module.
Note that a certain number of the operations invalidate events passed
as arguments to the function. This means that no further operations
are accessing on the event should be done after the function call.
The purpose of this limitation is to allow multiple implementations of
the event module with different memory allocation mechanisms. The
default implementation of events is purely functional and these rules
can be violated without causing problems. Other implementations of
the event module require that events be manipulated according to these
rules, and yet other implementations trace event modifications to
check that the rules are not violated. What this means is that
protocol designers do not need to be concerned with allocation and
deallocation issues, except in the final stages of development.
Currently a reference counting scheme is used for handling message
bodies, which form the bulk of memory used in Ensemble. Reference
counting is done by-hand, and events that reference Io-vectors
must be freed using the free function (see below). The rest of the
event is allocated on the ML heap, and is therefore freed
automatically by the ML garbage collector.
3.1 Fields
Events are ML records with fixed sets of fields. We refer to
type/event.mli for their type definitions and fields.
3.1.1 Extension fields
Events have a special field called the extension field. Uncommon
fields are included in up events as a linked list of extensions to
this field. The list of valid extensions is defined in
type/event.mli by the type definition fields.
3.1.2 Event Types
Events have a ``type'' field (called typ to avoid clashes with
the type keyword) in them which can take values from a fixed
set of enumerated constants. For the enumerations of the type fields
for events, we refer to appl/event.mli for the type
definitions for typ.
3.1.3 Field Specifiers
Events have defined for them a variant record called field.
These are called field specifiers. There is a one-to-one relation
between the fields in up and down events and the variants in the
fields specifiers. As will be seen shortly, lists of field specifiers
are passed to event constructor and modifier functions to specify the
fields in an event to be modified and their values. This allows
changes to an event to be specified incrementally.
3.2 Constructors
Events are constructed with the create function.
(* Constructor *)
val create : debug -> typ -> field list -> t
Create takes 3 arguments:
-
The string name of the module or location where this operation is being
performed. This is used only for debugging purposes and usually the value
name (defined to be the name of the current module) is used for
this argument.
-
The type of the event, which is a typ enumeration.
-
A list of field specifiers for changing the values of the fields in the new
events. Unmodified fields should not be accessed. For example, if an empty
list is passed as a field specifier then only the type field of the event will
be available in the event.
The return value of the constructor functions is a valid event.
3.3 Special Constructors
type/event.ml defines some special case constructors for either
performance or ease-of-coding reasons. All of these constructors are defined
using the create function or could be defined using them.
3.4 Modifiers
Events are modified with the set function.
(* Modifier *)
val set : debug -> t -> field list -> t
set takes 3 arguments:
-
The string name where this modification is taking place. Used only for
debugging purposes.
-
The event which is being modified. The event passed as an argument to this
function is invalidated: no further references should be made to the event.
-
A field specifier list. See the arguments description for Constructors.
The return value of set is a new event with the same fields as the
original event, except for the changes in the specifier list.
3.5 Copiers
Events are copied with the copy function.
(* Copier *)
val copy : debug -> t -> t
Copy takes two arguments:
-
The name where this modification is taking place. Used only for debugging
purposes.
-
The event to be copied.
The return value is a new event with its fields set to the same values as
the original.
3.6 Destructors
Events are released with the free function.
(* Destructor *)
val free : debug -> t -> unit
Free functions takes two arguments:
-
The name where this modification is taking place. Used only for debugging
purposes.
-
The event to be deallocated. This event becomes invalidated by this
function call. No further references to the event should be made.
The return value is the unit value.