Dining Philosophers Monitored | CPN Tools help |
Example Nets |
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 from:
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:
applet.html
file
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.
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.
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 ()
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
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 colour 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
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))
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:
GotLeft
is equal to all of the values in the PH
colour set, i.e. if the marking of the place is equal to the multi-set returned by the function PH.all()
. The function PH.all()
is one of the colour 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.
The initialization function for this monitor does nothing.
fun init (System'GotLeft_1_mark : PH ms, System'GotRight_1_mark : PH ms) = ()
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:
LeftFirst
transition has occurred and all philosophers have their left chopstick
RightFirst
transition has just occurred and all philosophers have their right chopstick
==
operator is used to check if two multi-sets 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
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) = ()
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);
The stop function for this monitor does nothing.
fun stop (System'GotLeft_1_mark : PH ms, System'GotRight_1_mark : PH ms) = ()