Overriding and extending Run State Transitions in Production Readout and
HPPreadout
Thanks to Constantine Vaman for inspiring this note. This note should
work with any version of the production readout or the high performance
production readout skeletons.
Background and Motivation
The Production readout framework is a flexible event segemnt based readout
system. While it is very clear how to do simple, and even complex event
readout applications, it is less clear how to hook into run state
transitions.
This application note will describe how to hook into the run state transitions.
In the production readout software, run states are managed by Tcl commands.
While there is a state transition manager much like Readout classic, a
natural way to hook into the run state transitions is to redefine the
actions taken for each Tcl command that controls a run state transition.
The classes that are responsible for implementing these commands are
all derived from StateTransitionCommand. They are (just add .h to the
class name to get the header filename):
CBeginCommand - Begins a run.
CEndCommand - Ends a run.
CPauseCommand - Temporarily pauses a run.
CResumeCommand - Resumes a paused run.
Each run state transition command has a pair of virtual member functions
that are intended as hooks to provide functionality both beofre and after
the state transition managed by the command. The base classes implement
no-op versions of these functions. The prototypes of these functions are:
int ExecutePreFunction()
int ExecutePostFunction()
While the functions return an int, the return value is currently ignored.
We can say that if the return value is ever used, a 0 return value will be
considered a success, while nonzero values will be considered errors.
What to do
You must do the following:
- Derive a class from the command you want to hook into, implement the
appropriate function(s) ExecutePreFunction or
ExecutePostFunction
- In Skeleton.cpp register an object from this class as a
command.
For example, to hook into the end command; you could define
#ifndef __MYEND_H
#define __MYEND_H
#include
class CTCLInterpreter;
class MyEnd : public CEndCommand
{
public:
MyEnd(CTCLInterpreter& interp);
virtual ~MyEnd();
private:
MyEnd(const MyEnd& rhs);
MyEnd& operator=(const MyEnd& rhs);
int operator==(const MyEnd& rhs) const;
int operator!=(const MyEnd& rhs) const;
public:
virtual int ExecutePreFunction();
virtual int ExecutePostFunction();
};
#endif
And implement as follows
// MyEnd implementation.
// Delegate excpet for the pre/post functions:
#include
#include "MyEnd.h"
#include "TCLInterpreter.h"
#include
MyEnd::MyEnd(CTCLInterpreter& rInterp) :
CEndCommand()
{
Bind(rInterp);
Register();
}
MyEnd::~MyEnd()
{
}
int
MyEnd::ExecutePreFunction()
{
cerr << "Beginning to end the run\n";
return 0;
}
int
MyEnd::ExecutePostFunction()
{
cerr << "Finished with the end run command\n";
return 0;
}
Then to Skeleton.cpp
#include "MyEnd.h"
...
void
CMyExperiment::AddUserCommands(CExperiment& rExperiment,
CInterpreterStartup& rStartup,
CInterpreterCore& rCore)
{
CReadoutMain::AddUserCommands(rExperiment, rStartup, rCore);
CTCLInterpreter& rInterp(rStartup.Interp());
new MyEnd(rInterp);
^^^ Add this line
// Add your command definitions after this comment. rInterp
// is a reference to the interpreter.
}
Full example
Full sample code is
available for download.
Last modified: Thu Sep 7 16:32:32 EDT 2006