rivet is hosted by Hepforge, IPPP Durham

The projection handler is a central repository for projections to be used in a Rivet analysis run. More...

#include <ProjectionHandler.hh>

Collaboration diagram for ProjectionHandler:

List of all members.

Public Types

enum  ProjDepth { SHALLOW, DEEP }
 Enum to specify depth of projection search. More...
typedef set< ProjHandleProjHandles
 Typedef for a vector of Projection pointers.
typedef map< string, ProjHandleNamedProjs
 Typedef for the structure used to contain named projections for a particular containing Analysis or Projection.

Public Member Functions

void clear ()
Projection registration
Todo:
This is a better form of singleton, which cleans up properly... but it can't yet be used as it highlights a projection memory problem. Please fix so we can use this!
const ProjectionregisterProjection (const ProjectionApplier &parent, const Projection &proj, const string &name)
 Attach and retrieve a projection as a reference.
const ProjectionregisterProjection (const ProjectionApplier &parent, const Projection *proj, const string &name)
 Attach and retrieve a projection as a pointer.
Projection retrieval. */
const ProjectiongetProjection (const ProjectionApplier &parent, const string &name) const
set< const Projection * > getChildProjections (const ProjectionApplier &parent, ProjDepth depth=SHALLOW) const

Static Public Member Functions

static ProjectionHandlergetInstance ()
 Singleton creation function.

Private Types

typedef map< const
ProjectionApplier
*, NamedProjs
NamedProjsMap

Private Member Functions

void removeProjectionApplier (ProjectionApplier &parent)
 Remove a ProjectionApplier: designed to only be called by ~ProjectionApplier (as a friend)
LoggetLog () const
 Get a logger.
Projection registration internal helpers
const Projection_getEquiv (const Projection &proj) const
const Projection_clone (const Projection &proj)
 Make a clone of proj, copying across child references from the original.
const Projection_register (const ProjectionApplier &parent, const Projection &proj, const string &name)
 Internal function to do the registering.
string _getStatus () const
 Get a string dump of the current ProjHandler structure.
bool _checkDuplicate (const ProjectionApplier &parent, const Projection &proj, const string &name) const
 Check that this parent projection doesn't already use this name.

Private Attributes

NamedProjsMap _namedprojs
ProjHandles _projs

Friends

class ProjectionApplier
 ProjectionApplier's destructor needs to trigger cleaning up the proj handler repo.

Construction. */

static ProjectionHandler_instance = 0
 ~ProjectionHandler ()
 Private destructor means no inheritance from this class.
ProjectionHandleroperator= (const ProjectionHandler &)
 The assignment operator is hidden.
 ProjectionHandler (const ProjectionHandler &)
 The copy constructor is hidden.
 ProjectionHandler ()
 The standard constructor.

Detailed Description

The projection handler is a central repository for projections to be used in a Rivet analysis run.

Without centralised projections, it can be hard to know which of an equivalent set of projections will be run on a particular event. In turn, this may mean that certain projections in the chain can go out of scope unexpectedly. There were originally also the issues that projections may need to be held as member pointers to an abstract base class, since post-construction setup is needed; that projections contained pointers to their own dependency chain, which could go out of scope; and that projection members could be modified after being applied to an event which, due to the caching model, would have unpredictable consequences.

By centralising all the projections, these issues are eliminated, as well as allowing analysis classes to contain fewer data members (since projections are now better accessed by name than by storing a data member reference or pointer).

The core of the ProjectionHandler design is that it is a singleton class, essentially a wrapper around a map of Projection*, indexed by a hash of the registering object and its local name for the registered projection.

Definition at line 41 of file ProjectionHandler.hh.


Member Typedef Documentation

typedef map<string, ProjHandle> NamedProjs

Typedef for the structure used to contain named projections for a particular containing Analysis or Projection.

Definition at line 52 of file ProjectionHandler.hh.

typedef map<const ProjectionApplier*, NamedProjs> NamedProjsMap [private]

Structure used to map a containing Analysis or Projection to its set of contained projections.

Definition at line 62 of file ProjectionHandler.hh.

typedef set<ProjHandle> ProjHandles

Typedef for a vector of Projection pointers.

Definition at line 48 of file ProjectionHandler.hh.


Member Enumeration Documentation

enum ProjDepth

Enum to specify depth of projection search.

Enumerator:
SHALLOW 
DEEP 

Definition at line 55 of file ProjectionHandler.hh.

{ SHALLOW, DEEP };

Constructor & Destructor Documentation

~ProjectionHandler ( ) [private]

Private destructor means no inheritance from this class.

Definition at line 38 of file ProjectionHandler.cc.

References ProjectionHandler::clear().

                                        {
    clear();
  }
ProjectionHandler ( const ProjectionHandler ) [private]

The copy constructor is hidden.

ProjectionHandler ( ) [inline, private]

The standard constructor.

Definition at line 88 of file ProjectionHandler.hh.

Referenced by ProjectionHandler::getInstance().

{ }

Member Function Documentation

bool _checkDuplicate ( const ProjectionApplier parent,
const Projection proj,
const string &  name 
) const [private]

Check that this parent projection doesn't already use this name.

Definition at line 192 of file ProjectionHandler.cc.

References ProjectionHandler::_getStatus(), ProjectionHandler::_namedprojs, Log::ERROR, ProjectionHandler::getLog(), ProjectionApplier::name(), and Projection::name().

Referenced by ProjectionHandler::registerProjection().

  {
    NamedProjsMap::const_iterator ipnps = _namedprojs.find(&parent);
    if (ipnps != _namedprojs.end()) {
      const NamedProjs pnps = ipnps->second;
      const NamedProjs::const_iterator ipph = pnps.find(name);
      if (ipph != pnps.end()) {
        const ProjHandle pph = ipph->second;
        getLog() << Log::ERROR << "Projection clash! "
                 << parent.name() << " (" << &parent << ") "
                 << "is trying to overwrite its registered '" << name << "' "
                 << "projection (" << pph << "="
                 << pph->name() << ") with a non-equivalent projection "
                 << "(" << &proj << "=" << proj.name() << ")" << endl;
        getLog() << Log::ERROR << _getStatus();
        return false;
      }
    }
    return true;
  }
const Projection * _clone ( const Projection proj) [private]

Make a clone of proj, copying across child references from the original.

Definition at line 92 of file ProjectionHandler.cc.

References ProjectionHandler::_namedprojs, Projection::clone(), ProjectionHandler::getLog(), Projection::name(), and Log::TRACE.

Referenced by ProjectionHandler::registerProjection().

  {
    // Clone a new copy of the passed projection on the heap
    getLog() << Log::TRACE << "Cloning projection " << proj.name() << " from " << &proj << endl;
    const Projection* newproj = proj.clone();
    getLog() << Log::TRACE << "Cloned projection " << proj.name() << " at " << newproj << endl;
    getLog() << Log::TRACE << "Clone types " << typeid(proj).name() << " -> " << typeid(newproj).name() << endl;

    // Copy all the child ProjHandles when cloning, since otherwise links to "stack parents"
    // will be generated by their children, without any connection to the cloned parent
    if (&proj != newproj) {
      NamedProjsMap::const_iterator nps = _namedprojs.find(&proj);
      if (nps != _namedprojs.end()) {
        getLog() << Log::TRACE << "Cloning registered projections list: "
                 << &proj << " -> " << newproj << endl;
        _namedprojs[newproj] = nps->second;
      }
    }

    return newproj;
  }
const Projection * _getEquiv ( const Projection proj) const [private]

Try to get an equivalent projection from the system

Returns:
0 if no equivalent projection found

Definition at line 139 of file ProjectionHandler.cc.

References ProjectionHandler::_projs, Rivet::EQUIVALENT, ProjectionHandler::getLog(), Projection::name(), Rivet::pcmp(), and Log::TRACE.

Referenced by ProjectionHandler::registerProjection().

  {
    // Get class type using RTTI
    const std::type_info& newtype = typeid(proj);
    getLog() << Log::TRACE << "RTTI type of " << &proj << " is " << newtype.name() << endl;

    // Compare to ALL projections via _projs collection
    getLog() << Log::TRACE << "Comparing " << &proj
             << " with " << _projs.size()
             << " registered projection" << (_projs.size() == 1 ? "" : "s") <<  endl;
    foreach (const ProjHandle& ph, _projs) {
      // Make sure the concrete types match, using RTTI.
      const std::type_info& regtype = typeid(*ph);
      getLog() << Log::TRACE << "RTTI type comparison with " << ph << ": "
               << newtype.name() << " vs. " << regtype.name() << endl;
      if (newtype != regtype) continue;
      getLog() << Log::TRACE << "RTTI type matches with " << ph << endl;

      // Test for semantic match
      if (pcmp(*ph, proj) != EQUIVALENT) {
        getLog() << Log::TRACE << "Projections at "
                 << &proj << " and " << ph << " are not equivalent" << endl;
      } else {
        getLog() << Log::TRACE << "MATCH! Projections at "
                 << &proj << " and " << ph << " are equivalent" << endl;
        return ph.get();
      }
    }

    // If no match, just return a null pointer
    return 0;
  }
string _getStatus ( ) const [private]

Get a string dump of the current ProjHandler structure.

Definition at line 174 of file ProjectionHandler.cc.

References ProjectionHandler::_namedprojs.

Referenced by ProjectionHandler::_checkDuplicate().

                                             {
    ostringstream msg;
    msg << "Current projection hierarchy:" << endl;
    foreach (const NamedProjsMap::value_type& nps, _namedprojs) {
      //const string parentname = nps.first->name();
      msg << nps.first << endl; //"(" << parentname << ")" << endl;
      foreach (const NamedProjs::value_type& np, nps.second) {
        msg << "  " << np.second << " (" << np.second->name()
            << ", locally called '" << np.first << "')" << endl;
      }
      msg << endl;
    }
    return msg.str();
  }
const Projection * _register ( const ProjectionApplier parent,
const Projection proj,
const string &  name 
) [private]

Internal function to do the registering.

Definition at line 119 of file ProjectionHandler.cc.

References ProjectionHandler::_namedprojs, ProjectionHandler::_projs, ProjectionHandler::getLog(), and Log::TRACE.

Referenced by ProjectionHandler::registerProjection().

  {
    ProjHandle ph(&proj);
    getLog() << Log::TRACE << "Registering new projection at " << ph << endl;

    // Add the passed Projection to _projs
    _projs.insert(ph);

    // Add the ProjApplier* => name location to the associative container
    _namedprojs[&parent][name] = ph;

    return ph.get();
  }
void clear ( )

Projection clearing method: deletes all known projections and empties the reference collections.

Definition at line 31 of file ProjectionHandler.cc.

References ProjectionHandler::_namedprojs, and ProjectionHandler::_projs.

Referenced by ProjectionHandler::~ProjectionHandler().

                                {
    _projs.clear();
    _namedprojs.clear();
  }
set< const Projection * > getChildProjections ( const ProjectionApplier parent,
ProjDepth  depth = SHALLOW 
) const

Get child projections for the given parent. By default this will just return the projections directly contained by the parent, but the depth argument can be changed to do a deep retrieval, which will recurse through the whole projection chain. In this case, there is no protection against getting stuck in a circular projection dependency loop.

Definition at line 233 of file ProjectionHandler.cc.

References ProjectionHandler::_namedprojs, ProjectionHandler::DEEP, and ProjectionHandler::SHALLOW.

Referenced by ProjectionApplier::getProjections().

  {
    set<const Projection*> toplevel;
    NamedProjs nps = _namedprojs.find(&parent)->second;
    foreach (NamedProjs::value_type& np, nps) {
      toplevel.insert(np.second.get());
    }
    if (depth == SHALLOW) {
      // Only return the projections directly contained within the top level
      return toplevel;
    } else {
      // Return recursively built projection list
      set<const Projection*> alllevels = toplevel;
      foreach (const Projection* p, toplevel) {
        set<const Projection*> allsublevels = getChildProjections(*p, DEEP);
        alllevels.insert(allsublevels.begin(), allsublevels.end());
      }
      return alllevels;
    }
  }

Singleton creation function.

Definition at line 14 of file ProjectionHandler.cc.

References ProjectionHandler::_instance, ProjectionHandler::getLog(), ProjectionHandler::ProjectionHandler(), and Log::TRACE.

                                                    {
    if (!_instance) {
      _instance = new ProjectionHandler();
      Log::getLog("Rivet.ProjectionHandler")
        << Log::TRACE << "Created new ProjectionHandler at " << _instance << endl;
    }
    return *_instance;
  }
const Projection & getProjection ( const ProjectionApplier parent,
const string &  name 
) const

Retrieve a named projection for the given parent. Returning as a reference is partly to discourage ProjectionApplier classes from storing pointer members to the registered projections, since that can lead to problems and there is no need to do so.

Definition at line 258 of file ProjectionHandler.cc.

References ProjectionHandler::_namedprojs.

Referenced by ProjectionApplier::getProjection().

                                                                               {
    //getLog() << Log::TRACE << "Searching for child projection '"
    //         << name << "' of " << &parent << endl;
    NamedProjsMap::const_iterator nps = _namedprojs.find(&parent);
    if (nps == _namedprojs.end()) {
      ostringstream msg;
      msg << "No projections registered for parent " << &parent;
      throw Error(msg.str());
    }
    NamedProjs::const_iterator np = nps->second.find(name);
    if (np == nps->second.end()) {
      ostringstream msg;
      msg << "No projection '" << name << "' found for parent " << &parent;
      throw Error(msg.str());
    }
    // If it's registered with the projection handler, we must be able to safely
    // dereference the Projection pointer to a reference...
    return *(np->second);
  }
ProjectionHandler& operator= ( const ProjectionHandler ) [private]

The assignment operator is hidden.

const Projection & registerProjection ( const ProjectionApplier parent,
const Projection proj,
const string &  name 
)

Attach and retrieve a projection as a reference.

Definition at line 47 of file ProjectionHandler.cc.

References ProjectionHandler::_checkDuplicate(), ProjectionHandler::_clone(), ProjectionHandler::_getEquiv(), ProjectionHandler::_register(), ProjectionHandler::getLog(), ProjectionApplier::name(), Projection::name(), and Log::TRACE.

Referenced by ProjectionApplier::_addProjection(), and ProjectionHandler::registerProjection().

  {
    getLog() << Log::TRACE << "Trying to register"
             << " projection " << &proj  << " (" << proj.name() << ")"
             << " for parent " << &parent << " (" << parent.name() << ")"
             << " with name '" << name << "'" << endl;

    // Check for duplicate use of "name" on "parent"
    const bool dupOk = _checkDuplicate(parent, proj, name);
    if (!dupOk) {
      cerr << "Duplicate name '" << name << "' in parent '" << parent.name() << "'." << endl;
      exit(1);
    }

    // Choose which version of the projection to register with this parent and name
    const Projection* p = _getEquiv(proj);
    if (p == 0) { // a null pointer is a non-match
      // If there is no equivalent projection, clone proj and use the clone for registering
      p = _clone(proj);
    }

    // Do the registering
    p = _register(parent, *p, name);

    // Return registered proj
    return *p;
  }
const Projection * registerProjection ( const ProjectionApplier parent,
const Projection proj,
const string &  name 
)

Attach and retrieve a projection as a pointer.

Definition at line 81 of file ProjectionHandler.cc.

References ProjectionHandler::registerProjection().

                                                                              {
    if (proj == 0) return 0;
    const Projection& p = registerProjection(parent, *proj, name);
    return &p;
  }
void removeProjectionApplier ( ProjectionApplier parent) [private]

Remove a ProjectionApplier: designed to only be called by ~ProjectionApplier (as a friend)

Definition at line 218 of file ProjectionHandler.cc.

References ProjectionHandler::_namedprojs, ProjectionHandler::_projs, and Rivet::pi.

Referenced by ProjectionApplier::~ProjectionApplier().

                                                                           {
    NamedProjsMap::iterator npi = _namedprojs.find(&parent);
    if (npi != _namedprojs.end()) _namedprojs.erase(npi);
    //
    const Projection* parentprojptr = dynamic_cast<Projection*>(&parent);
    if (parentprojptr) {
      ProjHandle parentph(parentprojptr);
      ProjHandles::iterator pi = find(_projs.begin(), _projs.end(), parentph);
      if (pi != _projs.end()) _projs.erase(pi);
    }
  }

Friends And Related Function Documentation

friend class ProjectionApplier [friend]

ProjectionApplier's destructor needs to trigger cleaning up the proj handler repo.

Definition at line 45 of file ProjectionHandler.hh.


Member Data Documentation

ProjectionHandler * _instance = 0 [static, private]
Todo:
Remove in favour of the static singleton function

Definition at line 91 of file ProjectionHandler.hh.

Referenced by ProjectionHandler::getInstance().

ProjHandles _projs [private]

Cache of Projections for reverse lookup, to speed up registering new projections as _namedprojs gets large.

Definition at line 70 of file ProjectionHandler.hh.

Referenced by ProjectionHandler::_getEquiv(), ProjectionHandler::_register(), ProjectionHandler::clear(), and ProjectionHandler::removeProjectionApplier().


The documentation for this class was generated from the following files: