Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Class Members | File Members | Related Pages

Object Registries names and descriptions.

The goal of the framework is to provide some capability of introspection to the application. Introspection allows programs to examine themselves, determine what objects are instantiated, and for what types as well as to get descriptive information about each object. For the spectrodaq client framework, introspection is achieved via:

For a simple application example see Registration Example below.

Object Registries and the ApplicationRegistry.

The intent of object registries and the application registry is to allow a program to determine what set of objects from what general class types are currently instantiated, and to get pointers to a specific object, given its name, for later manipulation. This registration of objects allows:

Each application using an application framework contains a single instance of an application registry. The static function CApplicationRegistry::getInstance retrieves a pointer to this registry.

Application registries are a subclass of the CClassifiedObjectRegistry class. classified object registries contain several CObjectRegistry objects. Each of these object registries is a dictionary of classes for a particular type of object.

Most classes in the framework are descended from the CRegisteredObject class. This class of object registers itself in the appropriate registry on construction, and removes itself from the appropriate registry on destruction. Subclasses usually provide two types of constructors:

The application registry can be searched for specific objects within a specific registry or the registries themselves can be iterated through and objects enumerated or searched for in each registry.

Object class hierarchy positioning information.

CNamedObject derived classes provide two member functions to support retrieving information about the place of the object in the class hierarchy. This is intended to be descriptive information, rather than information which can be used from within a program. (To programmatically manipulate object types, it is better to use the C++ RTTI subsystem.):

Object Description member functions.

CNamedObject derived classes implement the member function DescribeSelf(). DescribeSelf provides a human readable dump of the current state of an object. If you implement DescribeSelf() be sure to call your base class DescribeSelf so that the full state of the object can be produced.

Registration Example.

The example in this section shows how to create objects which make full use of the introspective features of the class hierarchy. The example creates two Events, a Timer event and a file event.

The file event accepts numeric input on stdin, locates the timer event by name, describes it and schedules it to run in single shot mode after n seconds where n is just the number the user typed in. If a non-numeric value is entered, the application exits.

#include <spectrodaq.h>
#include <SpectroFramework.h>
#include <iostream.h>
#include <unistd.h>
#include <stdlib.h>
#include <string>

//
// Timer class intended to be 'remote controlled' by name.
//
class MyTimer : public CTimerEvent
{
public:
  MyTimer(const char* pName);
  virtual void OnTimer();
  virtual string DescribeSelf();
};
//  The constructor registers us, with the given name, however
//  since we won't be enabled, the initial timeout is 0 and we create
//  ourselves in norepeat mode.
//
MyTimer::MyTimer(const char* pName) :
  CTimerEvent(pName, 0, false)
{
  AppendClassInfo();            // Add our place in class hierarchy.
}
//  OnTimer is called when the timer does expire.. it just types out
//  "Timer fired" and it's description.
//
void
MyTimer::OnTimer()
{
  cout << "A MyTimer object fired:" << endl;
  cout << DescribeSelf() << endl;
  cout << "------------------------------------------" << endl;
}
string 
MyTimer::DescribeSelf()
{
  string result;
  result = "My timer object (one shot remote controlled timer).\n";
  result += CTimerEvent::DescribeSelf();

  return result;
}


// Fd class to monitor stdin and remote control a timer based on numeric
// input.  Note that the thread exits if non-numeric input is received.
// 
class Stdin : public CFileEvent
{
  string m_TimerName;
public:
  Stdin(const char* pName, const string& rTimerName);
  virtual void OnReadable(istream &  rInput  );
  virtual string DescribeSelf();
protected:
  void         StartTimer(int nSeconds);
  CTimerEvent* LocateTimer();
};

// Constructor creates us on STDIN_FILENO registered as per name:
//
Stdin::Stdin(const char *pName, const string& rTimerName) : 
  CFileEvent(STDIN_FILENO, string(pName)),
  m_TimerName(rTimerName)
{
  AppendClassInfo();            // Add our place in class hierarchy.
}
//
// OnReadable reads a number, locates and fires off the timer:
//
void
Stdin::OnReadable(istream& rInput)
{
  char number[100];
  int  nsec;

  rInput >> number;
  nsec = atoi(number);

  if(nsec != 0) {
    StartTimer(nsec);
  }
  else {
    setEnable(false);           // Disable ourselves.
  }
}

// Describe ourself:
//
string
Stdin::DescribeSelf()
{
  string result;
  result = " Stdin  object controlling the timer: ";
  result += m_TimerName;
  result += '\n';
  result += CFileEvent::DescribeSelf();

  return result;
}
//
// Start timer locates the timer, sets its timeout and enables it:
//
void
Stdin::StartTimer(int nseconds)
{
  nseconds = nseconds * 1000;   // Timer needs milliseconds, not seconds.
  CTimerEvent* pTimer = LocateTimer();
  if(pTimer) {
    pTimer->SetTimeout(nseconds);
    pTimer->Enable();
  }
  else {
    cerr << "Stdin::StartTimer(): The timer " << m_TimerName;
    cerr << " Does not exist in: " << endl;
    cerr << DescribeSelf();
  }
}
//
//  Locates the named timer controlled by this StdIn object.
//
CTimerEvent*
Stdin::LocateTimer()
{
  CClassifiedObjectRegistry* pRegistry = CApplicationRegistry::getInstance();
  try {
    ObjectIterator p = pRegistry->Find(string("Events"), m_TimerName);
    return (CTimerEvent*)(p->second);
  }
  catch (CNoSuchObjectException& rExcept) { // Timer not found.
    return (CTimerEvent*)NULL;
  }
  
}

class MyApp : public DAQROCNode
{
protected:
  int operator()(int argc, char** argv);
};

MyApp theApplication;

int
MyApp::operator()(int argc, char** argv)
{
  // Create and describe the timer, but don't enable it.. that's done
  // by StdIn's object.

  MyTimer timer("A timer");
  cout << "Created a timer: " << timer.DescribeSelf() << endl;

  // Create an Stdin which controls the timer:

  Stdin TimerController("TimerControl", string("A timer"));
  cout << "Starting Stdin object: " << TimerController.DescribeSelf() << endl;
  TimerController.Enable();

  DAQThreadId id = TimerController.getThreadId();
  Join(id);
  
}

Generated on Thu Jan 6 16:58:46 2005 for Spectrodaq External Event Framework by  doxygen 1.3.9.1