This is an example that shows how to use user-defined monitors to establish communication between CPN Tools and an applet via external communication with Comms/CPN.
The net is a variation of the net for the Dining Philosophers. In the following it is assumed that you are familiar with the net for the Dining Philosophers.
In this net the philosophers pick up one chopstick at a time, whereas in the Dining Philosophers net, the philosophers pick up both the left and right chopsticks at the same time.
This net can be found in
<cpntoolsdir>/Samples/DiningPhilosophers/DiningPhilosophers_COMM_Mon.cpn
where <cpntoolsdir>
is the directory in which CPN Tools is installed.
The net can also be downloaded here.
The applet
A Java applet has been created to show how Comms/CPN can be used to establish communication between CPN Tools and an external process. This applet provides an alternative graphical representation of the markings of the net for the dining philosophers system. Each time a transition occurs in the net, the graphics shown by the applet are updated.
In the figure below, philosopher number 5 has both chopsticks and is eating, while philosopher number 2 has only picked up the right chopstick.
The files for the applet can be found in <cpntoolsdir>/Samples/DiningPhilosophers/applet
, or they can be downloaded from the help page for external communication with Comms/CPN.
The Java classes for the applet will not be described here.
Follow these steps to run the applet with the net described on this page:
- Start CPN Tools.
- Load the sample net
DiningPhilosophers_COMM_Mon.cpn
. - Apply the Rewind tool to the net to return to the initial marking.
- Load the applet on the computer where CPN Tools is running, e.g. by double-clicking on the
applet.html
file. - Apply the Play tool to the System page (the simulation feedback will not be updated until a connection has been made to the applet, see steps 6 and 7).
- Enter
9000
as the Port Number in the GUI for the applet. - Press the
Start
button in the applet. - Observe how the GUI for the applet reflects the marking of the CP-net.
Declarations for communication
There are two declarations that are used when communicating with the applet. The function send_to_applet
uses one of the Comms/CPN functions to send a string to the applet. The reference variable connected
is used in two user-defined monitors to check and/or indicate whether a connection to the applet has been established.
Communication using monitors and Comms/CPN
The two user-defined monitors for this net are named AppletComm
and Deadlock
. The AppletComm
monitor is associated with all five transitions on page System
, and the Deadlock
monitor is associated with two transitions and two places on the same page.
AppletComm
monitor
The AppletComm
monitor is associated with all of the transitions in the net. This means that the predicate function for the monitor will be invoked after every step in a simulation.
Initialization function
The initialization function is called once before a simulation starts. It checks to see if a communication connection exists between CPN Tools and the applet. If there is a connection, then the connection is closed, and the reference variable connected
is updated to indicate that the connection has been closed. The ConnManagementLayer.closeConnection
function is one of the Comms/CPN functions.
fun init () =
if !connected = true
then (ConnManagementLayer.closeConnection(“Conn 1”);
connected := false)
else ()
Predicate function
The predicate function is invoked after every step in a simulation, and it returns true each time one of the transitions in the net occurs.
fun pred (bindelem) =
let
fun predBindElem (System’LeftFirst (1, {p})) = true
| predBindElem (System’LeftScnd (1, {p})) = true
| predBindElem (System’PutDown (1, {p})) = true
| predBindElem (System’RightFirst (1, {p})) = true
| predBindElem (System’RightScnd (1, {p})) = true
| predBindElem _ = false
in
predBindElem bindelem
end
Observation function
The observation function is invoked each time the predicate function returns true, and it returns a pair of strings. The first value in the pair is a string representation of the variable p
which is of type PH
, and the second value is a string that indicates what event just occurred, i.e. which transition just occurred. The function PH.mkstr
is one of the color set functions.
fun obs (bindelem) =
let
fun obsBindElem (System’LeftFirst (1, {p})) = (PH.mkstr(p),”gotleft”)
| obsBindElem (System’LeftScnd (1, {p})) = (PH.mkstr(p),”eat”)
| obsBindElem (System’PutDown (1, {p})) = (PH.mkstr(p),”think”)
| obsBindElem (System’RightFirst (1, {p})) = (PH.mkstr(p),”gotright”)
| obsBindElem (System’RightScnd (1, {p})) = (PH.mkstr(p),”eat”)
| obsBindElem _ = (“”,””)
in
obsBindElem bindelem
end
Action function
Whenever the predicate function returns true, the value that is returned by the observation function will be passed to the action function. The action function will check whether a connection to the applet has been established. If there is no connection, then ConnManagementLayer.acceptConnection
function is invoked, and the simulation will be blocked until the applet opens a connection on port 9000. When a connection has been established, then the connected
reference variable is set to true. Finally, the send_to_applet
function is invoked with the string values that were passed from the observation function. The send_to_applet
is defined in a declaration, as described above.
fun action (s1,s2) =
(if not(!connected)
then (ConnManagementLayer.acceptConnection(“Conn 1”,9000);
connected:=true)
else ();
send_to_applet(s1,s2))
Stop function
The stop function is invoked when simulation stop criteria are fulfilled. If there is still a connection between CPN Tools and the applet, then the connection will be closed, and the reference variable connected
will be set to false. If the connection has already been disconnected, then nothing will happen when the stop function is invoked.
fun stop () =
if !connected = true
then (ConnManagementLayer.closeConnection(“Conn 1”);
connected := false)
else ()
Deadlock
monitor
The Deadlock
monitor is used to close the communication connection between CPN Tools and the applet if a simulation ends in a dead marking, i.e. in a marking in which there are no more enabled transitions. There are two dead markings for this net:
- When all philosophers have taken their left chopstick
- When all philosophers have taken their right chopstick
All philosophers have their left chopstick if the marking of place GotLeft
is equal to all of the values in the PH
color set, i.e. if the marking of the place is equal to the multiset returned by the function PH.all()
. The function PH.all()
is one of the color set functions. Checking whether all philosophers have their right chopstick is done in a similar manner.
The Deadlock
monitor is associated with the nodes shown in the group below.
Initialization function
The initialization function for this monitor does nothing.
fun init (System’GotLeft_1_mark : PH ms,
System’GotRight_1_mark : PH ms) = ()
Predicate function
The predicate function checks to see whether a dead marking has been reached. The predicate function is invoked when either the LeftFirst
or the RightFirst
transitions occur. The predicate function will return true in the two following situations:
- The
LeftFirst
transition has occurred and all philosophers have their left chopstick - The
RightFirst
transition has just occurred and all philosophers have their right chopstick
The ==
operator is used to check if two multisets are equal.
fun pred (bindelem,
System’GotLeft_1_mark : PH ms,
System’GotRight_1_mark : PH ms) =
let
fun predBindElem (System’LeftFirst (1, {p})) =
System’GotLeft_1_mark == PH.all()
| predBindElem (System’RightFirst (1, {p})) =
System’GotRight_1_mark == PH.all()
| predBindElem _ = false
in
predBindElem bindelem
end
Observation function
The observation function for this monitor does nothing, and it returns a unit value.
fun obs (bindelem,
System’GotLeft_1_mark : PH ms,
System’GotRight_1_mark : PH ms) = ()
Action function
The action function is used to close a connection between CPN Tools and the applet when a dead marking has been reached. When the action function is invoked, it will send the string deadlocked
to the applet, it will close the connection to the applet, and it will set the reference variable connected
to false.
fun action (observedval) =
(ConnManagementLayer.send(“Conn 1″,”deadlocked”,stringEncode);
ConnManagementLayer.closeConnection(“Conn 1”);
connected := false);
Stop function
The stop function for this monitor does nothing.
fun stop (System’GotLeft_1_mark : PH ms,
System’GotRight_1_mark : PH ms) = ()
You must be logged in to post a comment.