Singleton Functionality
CS applications often require that objects are instantiated only once. Using one node, the SuperProc inhibits to start one instance twice. But since the
CS is a distributed system, it is possible to start the same instance on more than one node at he same time. It could cause confusion or - even worse - hazards for man or machinery if different users act on the same hardware in parallel. Working in an unusually disciplined way and on the cost of flexibility, one could decide to start each object on a dedicated node only. More convenient and safe is singleton funtionality in an automated way. Therefore the "in use Flag Method" has been developed. It is implemented in most of PHELIX' classes which you can use as a template; see ...\CSClass\CSPHELIX\PH_RossRelais, for example.
Philosophy of the "in use Flag Method"
The
CS typically uses a DSC engine. This acts as a central instance which is read- and writable for each object. Therefore it can be used to deposit the information if and where an instance is in use. This requires only to add one memory tag. Following the CS convention, the default entry is N/A. This is read out by the constructor while instantiating an object. If the entry is N/A, the instance writes its node name to the tag and continues starting the object. The destructor overwrites the tag with N/A again. If meanwhile another user starts the same instance on another node, the node name of the first object is given back. The constructor can stop starting the instance in this case, and a pop up message informs the user that he should stop the object on node n first before he can start this instance again.
Tutorial how to use the "in use Flag Method"
In the directory ...\CSClass\CSCommon\TagTools three VIs can be found:
CS.get in use flag status.vi,
CS.set in use Flag up.vi and
CS.set in use Flag down.vi. The first two VIs are foreseen to be used in the constructor, the latter in the destructor of a class.
- Start the tag configuration editor and add a string memory tag (PHELIX convention ís to name it "Instancename"_in_use_Flag). Set N/A as default value.
- Place the CS.get in use flag status.vi in the constructor (see the example given below). Connect the DSCIntProc, the hostname (this information is easily available in classes which inherited from BaseProcess), and the name of the tag to be read out. The VI reads the tag connected at "Flag tag". If N/A or the hostname is returned, "instance not in use" is true. If another node is returned than the hostname, a pop up message informs the user that the instance is in use on node n; "instance not in use" is false in this case. If an error occurs while unpacking the data, a pop up message informs the user that the data from the DSC engine can not be read to check whether the instance is already in use; "instance not in use" is false in this case. If nothing (or explicitely "N/A") is connected to "Flag tag", nothing is done; "instance not in use" is true in this case.
- Depending on the result, as a next step the CS.set in use Flag up.vi can be used within the constructor. Connect the same input (DSCIntProc, hostname and tag name). This VI writes the hostname to the tag. If nothing (or explicitely "N/A") is connected to "Flag tag", nothing is done.
- Finally one should reset the tag entry using the CS.set in use Flag down.vi: It writes N/A to the tag. If nothing (or explicitely "N/A") is connected to "Flag tag", nothing is done.
Tricks
If you read the tutorial carefully, you may noticed some tricks within the "in use Flag Method". Anyhow, they are explained to be sure:
- The naming convention of PHELIX ("Instancename"_in_use_Flag) has one good reason: by "ref2name" the instance name is easily available and individual for each object of a class. If wanted, it can be easily created on the flight.
- Much more clever it is to put this name to the data base as in case of (most) PHELIX classes. Doing so, the data base entry can be set to N/A if the tag is (still) not created in the DSC engine. Therefore others can use such classes resigning the "in use Flag Method".
- In case of a node crash (where the destructor has not been able to destroy the instance in a controlled way "pulling the flag down"), the same object can be restarted at the same node again after restarting it. Hostname and tag entry have the same value in this case and the constructor creates the object. Therefore ther is no need of resetting the tag value by hand in case of a crash.
- The "in use Flag Method" is more powerfull than explained so far: It is also helpfull if you want to act on another object not knowing on which node it runs. This is explained in Finding Objects in a Distributed System.
Backfitting Classes
The "in use Flag Method" can easily be applied to (foreign) classes not changing these. Just create a new class which inherits from the class you want to apply this functionality to. Set up constructor and destructor. A critical point is to set up the ProcCases and ProcPeriodic VIs of it: Here you have to copy the ProcCases and ProcPeriodic of the class from which you inherited. This is forbidden by convention since they are
private. But this should not be our problem at this moment since it is a general design problem of the
CS. Anyhow, to see an example, compare the classes ...\CSClass\CSDelayGate\BNC555 and ...\CSClass\CSPhelix\PH_BNC555_SO; the later has singleton functionality as described above.
--
StefanGoette - 13 Sep 2005