imit_model / AnyLogic / UsersManual(AnyLogic)
.pdfAnyLogic V User’s Manual
postOffice |
PostOffice
recipient1 |
|
|
Class: Recipient |
|
Startup code: |
recipient2 |
input.registerAddress(); |
|
|
recipient3 |
Recipient |
|
Name: output
On receive action:
if( msg instanceof RegMsg ){ RegMsg rm = (RegMsg)msg; addresses.add( rm.source );
}
Additional class code:
Vector addresses = new Vector(); void sendTo(InfoMsg msg, Port destination){
msg.address = destination; send(msg);
}
Name: input
On receive action:
if (msg.address == this || msg.address == null ) {
return true;
}
else {
return false;
}
Additional class code: void registerAddress() {
RegMsg msg = new RegMsg (); msg.source = this;
send( msg );
}
Figure 89. Sending messages to specified addresses
You have implemented message sending to the specific recipients in your system: sent messages are accepted only by the recipients with the specified destination addresses.
7.4.7.1 Sending a message to a specific group of recipients
Now you need to implement periodical delivery to the specified groups of subscribers. You need to keep subscriber addresses lists at the post office and deliver periodicals only to members of these lists. The post office announces new periodical and a recipient subscribes on it by sending a confirmation message on announce reception.
Define the SubscrMsg message class to represent periodical announces. The periodName member variable carries the periodical name. The address member variable is used to carry the subscriber destination address in the confirmation message.
Type |
Name |
Default |
Port address
© 1992-2004 XJ Technologies http://www.xjtek.com |
187 |
Chapter 7. Message passing
String periodName
Define the PeriodicalMsg message class to represent periodicals. The addresses member variable is used to carry the subscriber addresses list. The periodical member variable represents the periodical itself.
Type |
Name |
Default |
|
|
|
periodical |
|
|
|
|
|
Vector |
addresses |
|
Type the following code in the Additional class code property of the output port.
String timesName = new String(“Times”);
String USATodayName = new String(“USA Today”);
Vector timesSubscribers = new Vector();
Vector USATodaySubscribers = new Vector();
void announcePeriodical( String periodicalName ){ SubscrMsg msg = new SubscrMsg(); msg.periodName = periodicalName;
send(msg);
}
The times and USAToday member variables keep information about “Times” and “USA Today” subscribers. The timesName and USATodayName member variables define periodical names. The announcePeriodical() method announces a subscription on a periodical. The periodical name is specified as the method parameter.
Substitute the code in the On receive action properties of input ports with the following code:
if ((msg instanceof MailMsg)&&((msg.address==this)||(msg.address==null) )){ //process a mail addressed to this recipient or to all recipients
return true;
}
else if ( msg instanceof SubscrMsg ) {
188 |
© 1992-2004 XJ Technologies http://www.xjtek.com |
AnyLogic V User’s Manual
if (subscribe){ msg.address = this;
send(msg); // subscribes to the periodical if subscribe is true
}
return true;
}
else {
PeriodicalMsg message = (PeriodicalMsg)msg; if message.addresses.contains(this){
// process periodical sent to this subscriber return true;
}
}
As shown above, if the recipient wants to subscribe to the announced periodical (it is defined by its subscribe member variable of boolean type), it returns the message to the post office in response to announce.
Substitute the code in the On receive action property of the output port with the following code:
if( msg instanceof RegMsg ){ RegMsg rm = (RegMsg)msg;
addresses.addElement( rm.source ); //add unknown address
}
else {
SubscrMsg sm = (SubscrMsg)msg;
if (sm.periodName.equals(timesName)) timesSubscribers.addElement(sm.address);
else if (sm.periodName.equals(USATodayName)) USATodaySubscribers.addElement(sm.address);
}
© 1992-2004 XJ Technologies http://www.xjtek.com |
189 |
Chapter 7. Message passing
Now the subscription messages are processed at the output port. The subscriber addresses are added to the corresponding address lists.
Specify the sendtoSubscribers() method in the Additional class code property of the output port.
void sendToSubscribers( Vector subscribers, PeriodicalMsg periodical ){
msg.addresses = subscribers;
port.send(msg);
}
Call this method to send periodicals to the specified group of subscribers, providing the subscriber address list and the message as method parameters. For instance, to deliver new “USA Today” issue to the subscribers, you should write:
PeriodicalMsg issue = new PeriodicalMsg();
sendToSubscribers( USATodaySubscribers, issue );
7.4.7.2Receiving a message only from a specific object or a group of objects
According to the message routing rules, ports accept every incoming message. However, it is frequently needed to receive a message only from a certain object or a group of objects, rather than from all of them.
Figure 90. Default message reception
190 |
© 1992-2004 XJ Technologies http://www.xjtek.com |
AnyLogic V User’s Manual
This task is bisymmetrical to the task described in section 7.4.7, “Sending a message to a specific recipient / a group of recipients”. Thus the implementation concept is the same: you need to define unique port identifiers to mark outgoing messages and filter messages at a recipient port by sender identifiers. Therefore, you need to define the message class with a custom field to carry the sender identifier and specify the list of authorized senders at the recipient object.
Name: objectA
Parameters:
String ID “first”
Name: objectB
Parameters:
String ID “second”
Name: objectC
Parameters:
String ID “third”
objectA |
objectB |
objectC |
recipient |
Class: Recipient |
|
|
Recipient |
Startup code: senders.addElement(“first”); senders.addElement(“third”);
Additional class code:
Vector senders = new Vector();
Figure 91. Making up authorized senders list
Again, as described in section 7.4.7, “Sending a message to a specific recipient / a group of recipients” you can build this list manually at the model design time as shown in Figure 91 or programmatically at runtime by implementing object registration mechanism described in section 7.4.5, “Getting information on connected objects” at the recipient object. Figure 92 shows one of possible implementations.
© 1992-2004 XJ Technologies http://www.xjtek.com |
191 |
Chapter 7. Message passing
objectA |
objectB |
objectC |
Class: Message
Parameters: source “first”
recipient |
a)
objectA |
objectB |
objectC |
Figure 92. Message filtering
recipient |
Class: Message
Parameters: source “second”
b)
7.4.8Verifying port connections at runtime
Sometimes you may need to verify port connections in your model. Port connection verifying is commonly used when your model has several port types and it’s essential to allow message passing only between ports of certain types. When editing your model you can establish connection with a port of forbidden type that causes a logic error. Therefore, you need to detect an invalid connection at runtime by implementing your own checking mechanisms. You can define specific actions to be performed on invalid connection detection, the most obvious is showing an error message using runtime error ability.
Suppose you need to detect invalid port connections in the simple manufacturing model. In this model a raw material supplier supplies product processing machines with raw material. After processing at a processing machine, a resulting product is delivered for the storage to a warehouse.
The model structure is shown in Figure 93. Raw material supplier is represented by supplier object, machine - by machine object, warehouse - by warehouse object.
supplier |
|
machIn |
|
machine |
|
|
warIn |
|
warehouse |
||
|
|
|
|
|
|
|
|
|
|
||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
prodOut |
|
|
|
|
|
machOut |
|
|
|
|
|
|
|
|
|
|
|
|
||
|
|
|
|
|
|
|
|
|
|
|
|
Figure 93. Simple manufacturing model
192 |
© 1992-2004 XJ Technologies http://www.xjtek.com |
AnyLogic V User’s Manual
Constructing the model from a great number of objects, you may establish invalid connections. Suppose you have made a mistake when editing your model – e.g., you have connected two output ports in error. In this case you can hardly detect the error: no error message will be displayed while your model will work incorrectly.
supplier1 |
supplier2 |
supplier3 |
machine1 |
machine2 |
machine3 |
warehouse1 |
Figure 94. Invalid port connection in the manufacturing model
If you have well-defined input and output ports in your model, you can detect invalid connection of two output ports by message arrival to an output port. Type the following code in the On receive action property of the output port to terminate the model simulation and show the error message on message reception at the port:
Engine.error("Error: The output " + this.getFullName() + " port has invalid
connection. "); //terminates simulation
Generally, you should implement a more sophisticated mechanism to check proper material flow in this model. According to the model logic, an entity sent by a supplier should be sent to a machine first and then to a warehouse. Thus, only the prodOut ports can be connected with the machIn ports and the machOut ports can be connected only with the warIn ports.
You can define a dedicated message class for each port class. Then each port class will send only the messages of the specific type and you can verify port connections by checking incoming message types.
In our model each entity is represented by its own message class: raw material is represented by a message of the Material type and a product – by a message of the Product type. The
© 1992-2004 XJ Technologies http://www.xjtek.com |
193 |
Chapter 7. Message passing
messages of the Material type should be received only at the machIn ports. Similarly, the messages of the Product type should be received only at the warIn port.
The checking procedure is specified in the On receive action property of the port. Type the following code to detect invalid connections of the machIn port:
if( ! (msg instanceOf Material) ){
Engine.error("Error: The " + this.getFullName() + " port has invalid connection. "); //terminates simulation
}
return true;
This code checks incoming message types. Only messages of Material type sent by prodOut ports are accepted. When a message of another type arrives to the port, the error message is shown.
Another approach consists in transmitting a reference to the sender port along with the message. Having got a reference to a port you can detect a connection with a port of forbidden type by checking the sender’s port type.
Let us demonstrate you how to implement this mechanism. Suppose you have ports of PortA and PortB types in your model and PortA ports can be connected only with the PortB ones. You need to detect invalid connections of the ports of the same type.
Create Message message class with the source field of type Port to carry a reference to message sender port. Specify Message message class in the Message type property of the ports.
To send a message via the port port, you should write the following code in the active object code:
Message msg = new Message();
msg.source = port;
send( msg );
The sent message carries the reference to the sender port.
The checking procedure is specified in the On receive action of the port. For instance, write the following code for the ports of PortA type to allow connections only with the PortB ports:
194 |
© 1992-2004 XJ Technologies http://www.xjtek.com |
AnyLogic V User’s Manual
if (!(msg.source instanceOf PortB))
Engine.error("Error: The " + this.getFullName() + " port is eroneously connected to the " + msg.source.getFullName() + " port." );
}
return true;
This code checks the sender’s port type. The message from non PortB port reception indicates the invalid port connection and the error message is shown.
7.4.9Defining message class constructors
You can initialize the created message data differently, depending on some external conditions. In AnyLogic you create a message instance by calling a message class constructor. The default constructor automatically generated by AnyLogic fills out all the fields of the created message instance in the same order you defined in the Parameters table. However, you may need to create the message with only a certain set of fields. For example, in the distributed database model, the data structure of the server response message depends on the type of the client query. You can define custom message class constructors to create messages with only those message fields that are necessary under the certain conditions.
For example, you need to model an elevator. A user controls the elevator by sending commands to the controller. A command may take a parameter or not, thus the data structure of the created message varies depending on the type of the command. Specifying your own constructors, you can create the command message with certain fields only.
Commands are represented by the messages of the Command class. The message class has the cmd member variable of type String representing the command instruction and the arg member variable representing the optional command argument.
Type Name Default
String cmd
Double arg
The “Move” command takes the parameter, specifying the movement step. In this case the default constructor is used to create the message.
© 1992-2004 XJ Technologies http://www.xjtek.com |
195 |
Chapter 7. Message passing
The default constructor creates a new message with all the fields initialized:
Command ( String cmd, double arg ) {
this.cmd = cmd;
this.arg = arg;
}
However, the “Stop” command does not take any parameters. Thus you can define the custom constructor to create a command message without any parameters. The message class constructor is defined in the Additional class code section of the message class properties:
Command ( String cmd ) {
this.cmd = cmd;
}
Calling different constructors you can create messages with different data structure. For example, the following lines of code create messages, representing “Move” and “Stop” commands correspondingly.
Command movecmd = new Command( “MOVE”, 20.0 );
Command stopcmd = new Command( “STOP” );
In the second case, the custom constructor is called to create the message with the cmd field only.
Note that Java statements you specified in the Constructor code section of the message class properties will be inserted in the default constructor only. Thus this code will be executed only in the case of creating a message instance by the default constructor.
7.4.10Modeling a LIFO queue
The default port queue in AnyLogic is the FIFO queue. However, you may need to model a LIFO queue – e.g., to model a LIFO buffer in queuing models. Messages are extracted from the LIFO queue in the Last-In First-Out order – i.e., the last placed in the queue message is extracted first as shown in Figure 95.
196 |
© 1992-2004 XJ Technologies http://www.xjtek.com |