[programmer/prog-manager.tex]

\section{Introduction}
%this chapter covers the manager API description
 \index{Core classes !dabc::Manager}
The \class{dabc::Manager} is the central singleton object of the
\dabc~ framework. 
It combines a number of different roles, such as:

\bcir
\item objects manager;
\item memory pools manager;
\item threads manager;
\item commands dispatcher;
\item run control state manager;
\item plug-in manager for factories and application;
\item implementation of control and configuration system
\ecir

Although these functionalities internally could as well be treated in
separate classes, \class{dabc::Manager} class defines the common
application programmer's interface to access most of these features.
Since the manager is a singleton,
these methods are available everywhere in the user code
by means of the static handle \func{dabc::mgr()->}.


The following section \ref{prog_manager_framework} describes such interface methods to
be used by the programmer of the \class{Module}, \class{Transport}, \class{Device}, and \class{Application} classes.
In contrast to this, section \ref{prog_manager_controls} gives a guide how to
re-implement the \class{Manager} class itself for a different control and configuration
system. This should be seldomly  necessary for the common DAQ designer, 
but is added here as a reference and as useful insight into the \dabc~ mechanisms.


\section{Framework interface}
\label{prog_manager_framework}
%here description of mostly used methods to be called from application, modules, etc.

\subsection{General object management}
\label{prog_manager_framework_objects}
All objects are organized in a folder structure and can be accessed
by the full path name. However, for most purposes it is recommended
to rather use higher level \class{Manager} methods to cause some
action(e.~g.~ \func{StartModule()}) than to work directly with the
primitive objects. 

\begin{description}

\item[\em Module* FindModule\small (const char* name)] :
Access to a \class{Module} by name. Returns $0$ if module does not exist.
   
\item[\em Port* FindPort\small (const char* name)]:
Access to a \class{Port} by name. Returns $0$ if port does not exist.
 
\item[\em Device* FindDevice\small (const char* name)] :
Access to a \class{Device} by name. Returns $0$ if device does not exist.


\item[\em WorkingThread* FindThread\small (const char* name, const char* required\_class = 0)] :
Access to a \class{WorkingThread} by name. The \func{required\_class} string may
be specified to check if the working thread implementation matches the client
intentions. Returns $0$ if thread object does not exist, or if it does not fullfill
\func{required\_class}.


\item[\em Application* GetApp()] : 
Access to the unique \class{Application} Object of this node.


	 
\end{description}

\subsection{Factory methods}	 
Since all \dabc~ objects are provided by  \class{dabc::Factory} plug-ins,
the application programmer needs to invoke corresponding factory methods to
instantiate them. However, the factories themselves should not be accessed by the
user code (although the \class{Manager} offers a getter method, see section
\ref{prog_manager_framework_objects}). Instead, creation and registration
of the key objects, like \class{Module} or \class{Device}, 
is done transparently by the \class{Manager} 
within specific creation methods. These will scan over all existing factories 
whether the corresponding factory method can provide an object of the requested class name.
In this case the object is created, kept in the object manager, and may be
addressed by its full name later.



\begin{description}
	 
\item[\em bool CreateModule\small (const char* classname, const char* modulename, const char* thrdname = 0)] : 
 \index{Manager interface !CreateModule()}
Instantiate a \class{Module} of class \func{classname} with the object name
\func{modulename}. Optionally, the name of the working thread \func{thrdname} may
be specified that shall run this module. If a thread of this name is already exisiting, 
it will be also applied for the new module; otherwise, a new thread of the name
will be created. If \func{thrdname} is not defined, \dabc~ will use module name for it.
Returns \keyw{true} or \keyw{false} depending on the instantiation success.

\item[\em bool CreateDevice\small (const char* classname, const char* devname)]:
\index{Manager interface !CreateDevice()} 
Instantiate a \class{Device} of class \func{classname} with the object name
\func{devname}. Returns \keyw{true} or \keyw{false} depending on the instantiation success.



% \item[\em ThreadRef CreateThread(const std::string& thrdname, const std::string& classname = 0, const std::string& devname = "", Command cmd = 0)] :



\item[\em bool CreateTransport\small (const char* portname, const char* transportkind, const char* thrdname = 0)] :
\index{Manager interface !CreateTransport()} 
Instantiate a \class{Transport} of the specified kind \func{transportkind} (e.~g.~ "mbs::ServerTransport")
and connect it to the port of full name \func{portname} (e.~g.~ "Readout/Input1").
Kind can specify device name, which than create appropriate transport instance.
Optionally the name of the working thread
\func{thrdname} may
be specified that shall run this transport. If a thread of this name is already exisiting, 
it will be also applied for the new transport; otherwise, a new thread of the name
will be created. If \func{thrdname} is not defined, \dabc~ will use a new 
thread automatically with an internal name.
Returns \keyw{true} or \keyw{false} depending on the instantiation success.

  
\item[\em bool CreateApplication\small (const std::string& classname = "", const std::string& appthrd = "")] :
\index{Manager interface !CreateApplication()}
Instantiate the \class{Application} of class \func{classname}. Optionally
the name \func{appthrd} of the main application thread may be specified.
Used in the \func{main()} function of the \dabc~ runtime executable on
inititialization time.

\end{description}	 


\subsection{Module manipulation}	

\begin{description}

\item[\em void StartModule\small (const char* modulename)] :
\index{Manager interface !StartModule()}
Enables the module of name \func{modulename} for processing.
Depending on the \class{Module} type (synchronous or asynchronous,
see section \ref{prog_overview_modules}), this will start
execution of the \func{MainLoop()}, or activate processing of the
queued events belonging to this module, resp.

\item[\em void StopModule\small (const char* modulename)] :
\index{Manager interface !StopModule()}
Disables processing for the module of name \func{modulename}.


\item[\em bool StartAllModules\small ()] :
\index{Manager interface !StartAllModules()}
Enables processing for all modules with apllication identifier number \func{appid}.
The optional identifier  may be set in the \func{Module} definition
to select different kinds of modules here. By default, this method will
start all exisiting modules on this node.
Returns \keyw{true} of \keyw{false} depending on success.

\item[\em bool StopAllModules\small ()] :
\index{Manager interface !StopAllModules()}
Disables processing for all modules with application identifier number \func{appid}.
The optional identifier  may be set in the \func{Module} definition
to select different kinds of modules here. By default, this method will
stop all exisiting modules on this node.
Returns \keyw{true} of \keyw{false} depending on success.

\item[\em bool DeleteModule\small (const char* modulename)] :
\index{Manager interface !DeleteModule()}
Deletes the module of name \func{modulename}. Returns \keyw{true} of  
\keyw{false} depending on the deletion success.

\item[\em bool IsModuleRunning\small (const char* modulename)] :
\index{Manager interface !IsModuleRunning()}
Depricated. Use FindModule(modulename).IsRunning() method instead.
Method returns \keyw{true} if module of name \func{modulename}
is running, i.~e.~ its processing is enabled. If module does not exist
or is not active, \keyw{false} is returned. 
         
\item[\em bool IsAnyModuleRunning()] :
\index{Manager interface !IsAnyModuleRunning()}
Method returns \keyw{false} if \strong{no} exisiting module is running anymore.
Otherwise returns \keyw{true}.

\item[\em bool ConnectPorts\small (const char* port1name,
                           const char* port2name,
                           const char* devname=0)] :
\index{Manager interface !ConnectPorts()} \\
Connects module \class{Port} of full name \func{port1name}
with another  module \class{Port} of full name \func{port2name}.
A full port name consists of the module name and a local port name,
separated by forward slash, e.~g.~ "Readout3/Output", "CombinerModule/Input2".
Optionally the \class{Device} name for the connection may
be defined with argument \func{devname}. By default, the ports are connected
with a FIFO-like transport of queued \class{Buffer} references in local memory.			   
			   
\end{description}

\subsection{Thread management}	

\begin{description}
	   
\end{description}
	 
\subsection{Command submission}	 
\label{prog_manager_framework_commands}	
\begin{description}
 
\item[\em bool Submit\small (Command cmd)] :
\index{Manager interface !Submit()}
This method generally submits a command \func{cmd} for execution.
The command is put in the queue of its command receiver working thread and is
then asynchronously executed there. The \class{Manager} will either forward the command
to its receiver, if such is specified as command parameter; or the \class{Manager} working thread itself will execute the command.
Thus method does not block and returns \keyw{true} if it accepts the command for execution, otherwise \keyw{false}.
Manager commands queue can also be used to submit command not only direct for manager,
but also for any other object on local or remote node. For that one from
several following functions \func{SetCmdReceiver} should be used.
      

\item[\em Command& SetReceiver\small (const char* itemname)] :
\item[\em Command& SetReceiver\small (Object* rcv)] :
\item[\em Command& SetReceiver\small (int nodeid, const char* itemname)] :


\index{Command interface !SetReceiver()}
Set receiver attribute of command \func{cmd}. The \func{itemname} is
item name of the local node like "Module1". One can also specify 
\func{nodename} or \func{nodeid} of the node, to which command should be submitted.
Returns pointer on the command itself.
One can use \func{SetCmdReceiver} to submit command like:
\begin{small}
\begin{verbatim}
dabc::mgr()->Submit(cmd.SetReceiver("Module1"));
dabc::mgr()->Submit(cmd.SetReceiver(1, "Module1"));
\end{verbatim}
\end{small}


\end{description}
 
\subsection{Memory pool management}	 	   

\begin{description}	

\item[\em bool CreateMemoryPool] {\small \bf\em (} \\
{\small \bf\em const char* poolname, unsigned buffersize, unsigned numbuffers, \\
          unsigned numincrement, unsigned headersize, unsigned numsegments)} : 
\index{Manager interface !CreateMemoryPool()}   
Instantiates a \class{dabc::MemoryPool} of name \func{poolname}, 
with \func{numbuffers} buffers of size \func{buffersize}.
If a pool of this name already exists, it will be extended.
The \func{numincrement} value specifies with how many buffers at once the memory pool 
can optionally be extended on the fly.
Optional arguments \func{headersize} and \func{numsegments} may
define the buffer header size, and the partition of the buffer segments, resp.         
The \class{MemoryPool} mechanisms are discussed in detail in 
section \ref{prog_services_memory}.
Method returns true or false depending on success.	

\item[\em Reference FindPool\small (const char* name)] :
\index{Manager interface !FindPool()}   
Access to memory pool by name \func{name}. Returns empty reference if not found.

\item[\em bool DeletePool\small (const char* name)] :
\index{Manager interface !DeletePool()}   
Delete memory pool of name \func{name}. Returns true or false depending on success.
   
\end{description}
	 

\subsection{Miscellaneous methods}
	 
\begin{description}	
 
\item[\em bool CleanupManager\small () ] :
\index{Manager interface !CleanupApplication()}   
Safely deletes all modules, memory pools and devices created
for user application. In the end all unused threads are also 
destroyed. 
 
\item[\em virtual void DestroyObject\small (Object* obj)] :
\index{Manager interface !DestroyObject()}   
Deletes the referenced object \func{obj} in manager thread.
Useful as safe replacement for call "delete this".

\item[\em void Print()] :
\index{Manager interface !Print()}   
Displays list of running threads and modules on \keyw{stdout}.


\end{description}




\section{Control system plug-in}
\label{prog_manager_controls}
For the common \dabc~ usage, the provided standard control and configuration system,
featuring DIM protocol \cite{DIM}, XML setup files, and a generic Java GUI,
will probably be sufficient.
However, if e.~g.~
an experiment control system is already existing and the data acquisition
shall be handled with the same means,
it might be necessary to adjust \dabc~ to another
controls and configuration framework.
Moreover, future developments may replace the current standard control
system by a more powerful, or a more convenient one.

Because of this, the connection between the \dabc~ core system and the
control system implementation was designed with a clear plug-in interface.
Again the \class{dabc::Manager} class plays here a key role.

This section covers all methods and mechanisms for
the control system plug-in. As an example, part \ref{prog_manager_controls_DIM}  
describes in detail the standard implementation as delivered with the \dabc~ distribution .



\subsection{Factory}
 \label{prog_manager_controls_factory}
A new control system plug-in is added into \dabc~ 
by means of a \class{dabc::Factory} subclass that  
defines the method
\func{bool CreateManagerInstance(const char* kind, dabc::Configuration* cfg)}.
This method should
create the appropriate \class{dabc::Manager} instance and return \keyw{true} 
if the name \func{kind}, as specified by the runtime environment,
matches the implementation.
The default \dabc~ runtime executable will also pass 
a configuration object \func{cfg} read from an XML file which may be
passed to the constructor of the \class{Manager}.

As it's mandatory for other \dabc~ factories, 
the \class{dabc::Factory} for the manager must be
instantiated as global object in the code that implements it.
This assures that the factory exists in the system on
loading the corresponding library.

\subsection{Manager}
\label{prog_manager_controls_manager}
Besides its role as a central singleton to access framework functionalities,
the \class{dabc::Manager} is also the interface base class for the 
control and configuration system that is applied with \dabc~. 

\subsubsection{Virtual methods}
The \class{dabc::Manager} defines several virtual methods concerning the {\em finite state machine},
the registration and subscription of parameters, the command communication
in-between nodes, and the management of a DAQ cluster, resp.
These methods have to be implemented for differrent kinds of control systems in
an appropriate subclass and are described as follows:

%\begin{compactdesc}
\begin{description}

\item[\em Manager(const char* managername,  bool usecurrentprocess, Configuration* cfg)] :
The constructor of the subclass. The recommended parameters 
are passed from the manager factory (see section \ref{prog_manager_controls_factory})
to the baseclass constructor, such as
the object name of the manager; optionally a
flag indicating to use either the main process or another thread for manager 
command execution;
and an optional configuration object \func{cfg}.

     
\item[\em\~{~}Manager()] :
The destructor of the subclass. It should cleanup and remove the  
control system implementation.    


\item[\em bool Subscribe(dabc::Parameter* par, int remnode, 
const char* remname)] :
\index{Manager interface !Subscribe()} 
This method shall link the value of a local parameter \func{par} to a remote parameter
of name \func{remname} that exists on node number \func{remnode} of the DAQ
cluster. Control system implementation may use a publisher-subscriber mechanism here
to update the local subscription whenever the remote parameter changes its value.

The actual update handler must call method \func{InvokeChange(const char* val)}
of the local \func {dabc::Parameter* par} then.
The new value \func{val} is passed to the parameter which 
will change itself appropriately. This decouples the parameter change
from the invoking control system callback in a thread-safe manner.

\item[\em bool Unsubscribe(dabc::Parameter* par)] :
\index{Manager interface !Unsubscribe()} 
The subscription of a local parameter \func{par} to a remote paramter by
a formerly called \func{Subscribe()} is removed from the control system.


\item[\em int NumNodes()] :
\index{Manager interface !NumNodes()} 
Returns the number of all nodes in the cluster. This value taken
from a configuration database, e.~g.~ an XML file.

\item[\em int NodeId() const] : 
\index{Manager interface !NodeId()} 
Returns the sequence id number of this node in the DAQ cluster.
This should be taken from the cluster configuration.

\item[\em bool IsNodeActive(int num)] : 
\index{Manager interface !IsNodeActive()} 
Returns \keyw{true} if DAQ cluster node of id number \func{num}
is currently active, otherwise \keyw{false}. 
This may allow to check on runtime if some of the
configured nodes are not available and should be excluded from the
DAQ setup.


\item[\em int ExecuteCommand(dabc::Command cmd)] :
\index{Manager interface !ExecuteCommand()}
This method executes synchronously any
\dabc~ command that is submitted to this manager itself.
It will run in the scope of the manager thread
(depending on constructor argument \func{usecurrentprocess}, 
this is either the main process thread, or a dedicated manager thread).

It may be re-implemented to add new commands required for the
controls implementation. The \dabc~ mechanism of
methods \func{SubmitCommand()} and \func{ExecuteCommand()} may allow
to decouple control system callbacks from their execution thread.

 
\end{description}
%\end{compactdesc}


\subsubsection{Baseclass methods}
\label{prog_manager_controls_base}
In addition to the virtual methods to be implemented in the manager subclass,
there is a number of \class{dabc::Manager} base class methods 
that should be called from the control system to perform actions of the 
framework:

\begin{description}

 
\item[\em bool DoStateTransition(const char* state\_transition\_cmd)] :
\index{Manager interface !DoStateTransition()}
Performs the state machine transition of name \func{state\_transition\_cmd}.
This method is synchronous and returns no sooner than the 
transition actions are completed (\keyw{true}) or an error is detected (\keyw{false}).
Note that the real transition actions are still user defined in methods
of the \class{dabc::Application} implementation.

\item[\em bool IsTransitionAllowed(const char* state\_transition\_cmd, bool errout)] :
\index{Manager interface !IsTransitionAllowed()}
Checks if state transition of name \func{state\_transition\_cmd} is allowed
for the default state machine implementation (which should be reproduced exactly by
any external SM implementation) and returns \keyw{true} or \keyw{false}, resp. Argument
\func{errout} may specify if error messages shall be printed to {\tt stdout}.

\item[\em void RecvOverCommandChannel(const char* cmddata)] :
\index{Manager interface !RecvOverCommandChannel()}
Receives a \dabc~ command as text stream \func{cmddata} 
from a remote node. Usually this function should be called in a
receiving callback of the control system communication layer,
passing the received command representation to the core system.
Here the command object is unstreamed again, forwarded to its
receiver and executed.

This is the pendant to virtual method 
\func{SendOverCommandChannel()} which should implement the \strong{sending} 
of a streamed command from the core to a remote manager by transport mechanisms of the control system. 

 
 
\end{description}






\subsection{Implementation for DIM}
\label{prog_manager_controls_DIM}
The \dabc~ provides controls module, based on the DIM library \cite{DIM} and 
is marked by namespace \class{dimc::} (for "DIM Control"). 
% It features the DIM publisher-subscriber mechanism with \dabc~ process records 
and uses state machine module and XML parser as provided by the \dabc~core system. 
The main classes are described in the following:

\subsubsection{\class{dimc::Observer}}
\label{prog_manager_controls_DIM_observer}
\index{DIM Control classes ! dimc::Observer}
Implements the control system interface of \class{dabc::Worker} as described above. 

\begin{compactenum}

\item It uses the \strong{state machine} of the \dabc~ core system.

\item It exports a dedicated \class{dabc::StatusParameter} that is
synchronized with the value of the state machine in \func{ParameterEvent()}. 
This parameter is required to display the state of the node on the generic
Java GUI.

\item It applies the generic \class{dabc::Configuration}  for setting up
the node properties. The standard executable \decl{dabc\_run}  will create 
this object from parsing an XML file. 

\item The other interface functionalities use one
component of class \class{dimc::Registry}.

\end{compactenum}




\subsubsection{\class{dimc::Registry}}
\label{prog_manager_controls_DIM_registry}
\index{DIM Control classes ! dimc::Registry}
The main component of the \class{dimc::Manager} that
offers service methods really implementing the manager interface.
It registers all parameters, commands, and subscriptions; 
and it defines the allowed access methods for the DIM server itself.
 
\begin{compactenum}

\item The \strong{DIM server} is instantiated in the constructor as	 \class{dimc:Server}
singleton. Methods \func{StartDIMServer()} and \func{StopDIMServer()} 
actually initiate and terminate the service. 

\item \strong{Naming of nodes and services:}
Method \func{GetNodeName(int num)} of \class{dimc::Manager} 
uses \func{CreateDIMPrefix(num)} of \class{dimc::Registry}.
This evaluates the unique name for node number \func{num} 
from the \class{dabc::Configuration} object: It consists of
a global prefix ("DABC"), the configuration \func{NodeName()}, and the
\func{ContextName()} property of the node id,
all separated by forward slashes ("/").

The node name is also taken as prefix for the helper
methods \func{BuildDIMName()} (\func{ReduceDIMName()}, resp.) that 
transform local \dabc~ parameter and command names 
into unique DIM names (and back, resp.). 
Moreover, methods \func{CreateFullParameterName()}
(\func{ParseFullParameterName()}, resp.) define how
the local parameter name itself is composed (decomposed, resp.) from the names
of its parent module and its internal variable name. They
utilize corresponding static methods of class \class{dimc::nameParser}
in a thread-safe way.

     
\item \strong{Parameter export:} \func{dimc::Manager::ParameterEvent()}
uses methods \func{RegisterParameter()} (and
\func{UnregisterParameter()}, resp.) to declare (undeclare, resp.) 
a corresponding DIM service. Here the \class{dimc::Registry}
keeps auxiliary objects of class 
\class{dimc::ServiceEntry} that link the \class{DimService} with the \class{dabc::Parameter} (see section \ref{prog_manager_controls_DIM_servicentry}). 
On parameter change, method 
\func{ParameterUpdated()} will initiate an update of the corresponding DIM
service.
    
\item \strong{Control system commands:} Method \func{DefineDIMCommand(const char* name)} 
creates and registers simple (char array) \class{DimCommand} objects
that may be executed on this node. The \class{dimc::Registry} constructor
defines commands for all state machine transitions, 
such as Configure, Enable, Halt, Start, Stop. Additionally, there are DIM commands for
shutting down the node, setting a parameter value, and
wrapping a \dabc~ 
command as string representation ({\em "ManagerCommand"} for \func{SendOverCommandChannel()},
see section \ref{prog_manager_controls_manager}), resp.

Moreover, a \dabc~ module may register a 
\class{dabc::Command} as new control system command on the fly.
In this case \class{dimc::Manager} method
\func{CommandRegistration()} will use
\func{RegisterModuleCommand()} of \class{dimc::Registry}.
This will both define  a \class{DimCommand}, and
publish a corresponding command descriptor as DIM service to
announce the command structure to the generic Java GUI.
Method \func{UnRegisterModuleCommand()} may remove command and 
descriptor service again.


When the DIM server receives a remote command, 
method \func{HandleDIMCommand()} checks if this command
is registered; then \func{OnDIMCommand()} will transform the
\class{DimCommand} into a \class{dabc::Command} and \func{Submit()}
this to the Manager. The actual command execution will thus happen
in re-implemented method \func{ExecuteCommand()} of \class{dimc::Manager}.
Thus the command action runs independent of the DIM commandhandler thread.

\item \strong{Parameter subscription:}
Method \func{Subscribe()} (\func{Unsubscribe()}, resp.) of \class{dimc::Manager} 
are forwarded to \func{SubscribeParameter()} (UnsubscribeParameter() , resp. ) 
of \class{dimc::Registry}.
These implement it by means of the \class{DimService} update mechanism. 
Subscriptions are kept as vector of \class{dimc::DimParameterInfo} objects
(see section \ref{prog_manager_controls_DIM_parinfo}).

\item \strong{Remote command execution:}   
Method \func{SendOverCommandChannel()} of \class{dimc::Manager}    
is forwarded to  \func{SendDimCommand()} of \class{dimc::Registry}.
The streamed \class{dabc::Command} is wrapped as text argument
into the DIM {\em ManagerCommand} and send to the destination
by node name via \func{DimClient::sendCommand()}.    
    
    
    
\end{compactenum}    

\subsubsection{\class{dimc::Server}}
\label{prog_manager_controls_DIM_server}
\index{DIM Control classes ! dimc::Server}    
Subclass of DIM class \class{DimServer}, implementing command handler, error handler, and exit handlers for client and server exit events.

\begin{compactenum}

\item Because most DIM server actions are invoked by static methods of \class{DimServer}, it is reasonable to have only one instance of \class{dimc::Server}; 
thus this class is designed as \strong{singleton pattern}. Access and initial creation is provided by method \func{Instance()}. A safe cleanup is granted by \func{Delete()} (ctors and dtors are private and cannot be invoked directly).

\item The \class{dimc::Registry} is set as "owner" of \class{dimc::Server} by means
of a back pointer. All handler methods of the \class{DimServer} are
implemented as forward calls to corresponding methods of the 
\class{dimc::Registry} and treated there, such as:
\bcir
	\item \func{commandHandler()} to \func{HandleDIMCommand()}
	\item \func{errorHandler()} to \func{OnErrorDIMServer()}
	\item \func{clientExitHandler()} to \func{OnExitDIMClient()}
	\item \func{exitHandler()} to \func{OnExitDIMServer()}
\ecir


    
\end{compactenum}

    
\subsubsection{\class{dimc::ServiceEntry}}
\label{prog_manager_controls_DIM_servicentry}
\index{DIM Control classes ! dimc::ServiceEntry}
This is a container to keep the \class{DimService} together with 
the corresponding \class{dabc::Parameter} object and some extra properties.
The \class{dimc::ServiceEntry} objects are managed by the
\class{dimc::Registry} and applied for the 
\func{RegisterParameter()}  method.


\begin{compactenum} 

\item For \class{std::string} parameters an internal \class{char*} array is used as buffer which is actually exported as DIM service.

\item Method \func{UpdateBuffer()} updates the DIM service; it optionally may copy the
parameter contents to the buffer before.

\item Method \func{SetValue()} sets the \class{dabc::Parameter} to a new value, as defined by a string expression.

\end{compactenum}


\subsubsection{\class{dimc::ParameterInfo}}
\label{prog_manager_controls_DIM_parinfo}
\index{DIM Control classes ! dimc::ParameterInfo}
A subclass of DIM class \class{DimStampedInfo} which subscribes
to be informed if a remote DIM service changes its value. 
The \class{dimc::ParameterInfo} objects are managed by the
\class{dimc::Registry} and applied for the \func{Subscribe()} method.

\begin{compactenum} 

\item The \class{dimc::ParameterInfo} has a reference to
a local \class{dabc::Parameter} object that shall be updated
if the subscribed service changes. 

\item Depending on the subscribing \class{dabc::Parameter} type
(integer, double, string,...), the constructor will
instantiate an appropriate \class{DimStampedInfo} type.

\item Method \func{infoHandler()} of \class{DimStampedInfo} 
is implemented to update the parameter to the new value
by means of an \func{InvokeChange()} call.

\end{compactenum}

   
 
 