Defining New Data Types
There is a limited form of user-defined type, the Message type.
The MLDesigner contains a heterogeneous message interface, which provides a mechanism for primitives to transmit arbitrary objects to other primitives. It’s design fulfills the following requirements:
- Existing primitives (primitives that were written before the message interface was added) that handle ANYTYPE work with message particles without change.
- Message portholes can send different types of messages during the same simulation. This is especially useful for modeling communication networks.
- It avoids copying large messages by using a reference count mechanism, as in many C++ classes (for example, string classes).
- It is possible to safely modify large messages without excessive memory allocation and deallocation.
- It is (relatively) easy for users to define their own message types. No change to the kernel is required to support new message types.
The message type is interpreted by MLDesigner as a particle containing a message. There are three classes that implement the support for message types:
- The Message class is the base class from which all other message data types are derived. A user who wishes to define an application-specific message type derives a new class from Message.
- The Envelope class contains a pointer to a derived class from Message. When an Envelope object is copied or duplicated, the new envelope simply sets its own pointer to the pointer contained in the original. Thus, several envelopes can reference the same Message object. Each Message object contains a reference count, which tracks how many Envelope objects reference it. When the last reference is removed, the Message is deleted.
- The MessageParticle class is a type of Particle (like IntParticle, FloatParticle, etc.). It contains an Envelope. Ports of type message transmit and receive objects of this type.
Class Particle contains two member functions for message support: getMessage, to receive a message, and the << operator with an Envelope as the right argument, to load a message into a particle. These functions return errors in the base class. They are overridden in the MessageParticle class with functions that perform the expected operation.
Defining a New Message Class
Every user-defined message is derived from class Message. Certain virtual functions defined in that class must be overridden, others may optionally be overridden. Here is an example of a user-defined message type:
Use of the Envelope Class
The Envelope class references objects of the Message class or derived classes. Once a message object is placed into an envelope object, the envelope takes over the responsibility for managing its memory: maintaining reference counts and deleting the message when it is no longer needed.
Use of the MessageParticle Class
If a porthole is of type message, its particles are objects of the class MessageParticle. A MessageParticle is simply a particle whose data field is an Envelope, which means that it can hold a Message in the same way that Envelope objects do.
Use of Messages in Primitives
Here are a couple of simple examples of primitives that produce and consume messages.