Next: Required and Generated
Up: A USERS GUIDE
Previous: Dynamic Configuration/ User
One advantage of working in C++ is that part of the work of writing
a module is done for the user by inheriting behavior from a Module parent
class (AppModule) provided by the framework package. Below is a selection
from the AppModule class declaration. The full declaration is not included
because it contains many unimportant details:
class AppModule : public APPExecutable { // AppModule inherits from APPExecutable
//------------------
// Static Members --
//------------------
protected:
static AbsEvent* _theAbsEvent; // a pointer to the event
//--------------------
// Instance Members --
//--------------------
public:
// Constructors
AppModule( const char* const theName, const char* const theDescription );
// Destructor
virtual ~AppModule( );
// Operations
virtual void begin( AppJob* aJob );
virtual void begin( AppRun* aRun );
virtual AbsEvent* event( AbsEvent* anEvent, int mode = 0 );
virtual void other( AbsEvent* anOther );
virtual void end ( AppRun* aRun );
virtual void end ( AppJob* aJob );
virtual void abort( AppJob* aJob );
virtual void talkTo( );
virtual void help( );
virtual void exit( );
...
};
Notes:
- Each of the above operations represent processing steps that will be
called by AC++ when the appropriate state is reached.
- The constructor for the module takes a name that will be used to identify
the created module-instance (see section on module-instances) in any user
interface command. The ``theDescription'' argument is for informational
purposes only.
- Function overloading differentiates the begin( ) and end( )
functions.
Here is an example user
module class definition:
class ParmExample : public AppModule { // ParmExample inherits from AppModule
//--------------------
// Instance Members --
//--------------------
public:
// Constructors
ParmExample( const char* const theName, const char* const theDescription );
// Destructor
virtual ~ParmExample( );
// Operations
virtual void begin( AppJob* aJob );
virtual AbsEvent* event( AbsEvent* anEvent, int mode = 0 );
protected:
// example parameter variables which adjust the behavior of the module
AbsParmGeneral<double> _parm1, _parm2;
};
Notes:
- _parm1 and _parm2 are the member data of this module
class. Because they are of type AbsParmGeneral<T> they are set-able via
a talk_to. Member data of type AbsParmGeneral<T> are analogous to parameter
sets in ANALYSIS_CONTROL. However any data item that is needed by more then one operation of
the module should go here even if it is not meant to be a member of a parameter
set or be setable by a talk to.
- The user module inherits from AppModule. This means that many of
the module operations are actually implemented in the parent class. Only
the entries that stpana needs to specialize are declared here. The most
significant default behavior is the talk_to method. This no longer needs
to be written by the user module since the only behavior ParmExample needs is
that the talk_to be able to set the _parm1, and _parm2 variables.
The ability to set class data variables that are declared to the framework package
is the one thing that AppModule:talk_to method knows how to do. Besides
the obvious advantage that users no longer write talk-to's the other advantage
is that uniformity in the end-user interface is enforced. No longer will the
way to set variables vary from module to module. The equivalent of .uic files
(which are now .tcl files) will look naturally become more uniform.
- The event member function, takes a pointer to the AbsEvent
as a passed argument and returns an optionally modified version of it. This
is the way that modules access event data. The fact that the event is passed
by pointer means that the framework code itself needs to know very little
about the event data structure. This is what allows CDF and BaBar to share
this code. It also means that if we change our minds about what an event
is, the framework code will need minimal modification.
- The second argument to the event operation, ``mode'' is not used at CDF.
Here is the implementation file for the above example:
...
//----------------
// Constructors --
//----------------
ParmExample::ParmExample(
const char* const theName,
const char* const theDescription )
: AppModule( theName, theDescription ), // Pass args. to parent class
_parm1("parm1", this, 1), // Initialize parm1 to 1
_parm2("parm2", this, 2) // Initialize parm2 to 2
{
// Add parameters to list of command handlers
commands( )->append( &_parm1 );
commands( )->append( &_parm2 );
}
//--------------
// Destructor --
//--------------
ParmExample::~ParmExample( )
{
}
//--------------
// Operations --
//--------------
void
ParmExample::begin( AppJob* )
{
cout << name( ) << " begin Job" << endl;
printAllAbsParm(cout); // formated print out of default values
}
AbsEvent*
ParmExample::event( AbsEvent* anEvent, int )
{
cout << name() << " parm values: "<< _parm1.value() << " " << _parm2.value() << endl;
return (AbsEvent*)anEvent;
}
Notes:
- This example uses the C++ initializer syntax. The name of the constructor
and its arguments is followed by a ``:'' and then a list of things to initialize
including the parent class. Here the parent class is being initialized with
the arguments passed to the child class constructor. Then the member data of
the ParmExample class is being initialized by calling the three argument
constructor of AbsParmGeneral<double> (which is the type of _parm1, _parm2).
The first argument is a string that will be used as the command name for
changing the parameter in a talk-to. The second argument is a pointer to
the module that this command/parameter belongs to. (In C++ ``this'' is
a compiler defined pointer to the current class object, in this case it refers
to the instance of ParmExample that is being constructed.) The third argument
is the default value the parameter should have.
- In the begin job operation a friend function of AbsParm is called in
order to print the default values of the module instance.
- In the event operation the values are again echo'ed. At this point they
may have been changed via a talk-to, with a command like this:
module talk ParmExample2; parm2 set 1111; exit
Next: Required and Generated
Up: A USERS GUIDE
Previous: Dynamic Configuration/ User
Liz Sexton
Fri May 16 16:37:56 CDT 1997