A Maisie program is a collection of entity definitions and C functions. An entity definition (or an entity type) describes a class of objects. An entity instance, henceforth referred to simply as an entity, represents a specific object in the physical system and may be created and destroyed dynamically. An entity is created by the execution of a new statement and is automatically assigned a unique identifier on creation. For instance, the following statement creates a new instance of a manager entity and stores its identifier in variable r1.
r1 = new manager{10};
Entities communicate with each other using buffered message-passing. Maisie defines a type called message, which is used to define the types of messages that may be received by an entity. Definition of a message-type is similar to a struct; the following declares a message-type called req with one parameter (or field) called count.
message req {int count;};
Every entity is associated with a unique message-buffer. A message is deposited in the message buffer of an entity by executing an invoke statement. The following statement will deposit a message of type req with timestamp clock()+t, where clock is the current value of the simulation clock, in the message buffer of entity m1.
invoke m1 with req(2) [after t]
If the after clause is omitted, the message is timestamped with the current simulation time. An entity accepts messages from its message-buffer by executing a wait statement. The wait statement has two components: an optional wait-time (tc) and a required resume-block. If tc is omitted, it is set to an arbitrarily large value. The resume-block is a set of resume statements, each of which has the following form:
mtype(m) [st b] statement;
where m is a message-type, b an optional boolean expression referred to as a guard, and statement is any C or Maisie statement. The guard is a side-effect free boolean expression that may reference local variables or message parameters. If omitted, the guard is assumed to be the constant true. The message-type and guard are together referred to as a resume condition. A resume condition with message-type m and guard b is said to be enabled if the message buffer contains a message of type m, which if delivered to the entity would cause b to evaluate to true; the corresponding message is called an enabling message.
With the wait-time omitted, the wait statement is essentially a selective receive command that allows an entity to accept a particular message only when it is ready to process the message. For instance, the following wait statement consists of two resume statements. The resume condition in the first statement ensures that a req message is accepted only if the requested number of units are currently available (the requests are serviced in first-fit manner). The second resume statement accepts a free message:
wait until
{ mtype(req) st (units >= msg.req.count)
/* signal requester that request is granted */
or mtype(free) /* return units to the pool */
}
If two or more resume conditions in a wait statement are enabled, the timestamps on the corresponding enabling messages are compared and the message with the earliest timestamp is removed and delivered to the entity. If no resume condition is enabled, a timeout message is scheduled for the entity tc time units in the future. The timeout message is canceled if the entity receives an enabling message prior to expiration of tc; otherwise, the timeout message is sent to the entity on expiration of interval tc. A hold statement is provided to allow an entity to suspend itself for a given duration.