#include <ProjectionHandler.hh>
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 42 of file ProjectionHandler.hh.
Public Types | |
enum | ProjDepth { SHALLOW, DEEP } |
Enum to specify depth of projection search. More... | |
typedef set< ProjHandle > | ProjHandles |
Typedef for a vector of Projection pointers. | |
typedef map< const string, ProjHandle > | NamedProjs |
Typedef for the structure used to contain named projections for a particular containing Analysis or Projection. | |
Public Member Functions | |
void | clear () |
Projection registration | |
const Projection & | registerProjection (const ProjectionApplier &parent, const Projection &proj, const string &name) |
Attach and retrieve a projection as a reference. | |
const Projection * | registerProjection (const ProjectionApplier &parent, const Projection *proj, const string &name) |
Attach and retrieve a projection as a pointer. | |
Projection retrieval. */ | |
const Projection & | getProjection (const ProjectionApplier &parent, const string &name) const |
set< const Projection * > | getChildProjections (const ProjectionApplier &parent, ProjDepth depth=SHALLOW) const |
Static Public Member Functions | |
static ProjectionHandler * | create () |
Singleton creation function. | |
static void | destroy () |
Singleton deletion function. | |
Private Types | |
typedef map< const ProjectionApplier *, NamedProjs > | NamedProjsMap |
Private Member Functions | |
~ProjectionHandler () | |
Private destructor means no inheritance from this class. | |
ProjectionHandler & | operator= (const ProjectionHandler &) |
The assignment operator is hidden. | |
ProjectionHandler (const ProjectionHandler &) | |
The copy constructor is hidden. | |
void | removeProjectionApplier (ProjectionApplier &parent) |
Remove a ProjectionApplier: designed to only be called by ~ProjectionApplier (as a friend). | |
Log & | getLog () const |
Get a logger. | |
Construction. */ | |
ProjectionHandler () | |
The standard constructor. | |
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 |
Static Private Attributes | |
static ProjectionHandler * | _instance = 0 |
Friends | |
class | ProjectionApplier |
ProjectionApplier's destructor needs to trigger cleaning up the proj handler repo. |
typedef set<ProjHandle> ProjHandles |
typedef map<const string, ProjHandle> NamedProjs |
Typedef for the structure used to contain named projections for a particular containing Analysis or Projection.
Definition at line 53 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 63 of file ProjectionHandler.hh.
enum ProjDepth |
~ProjectionHandler | ( | ) | [private] |
Private destructor means no inheritance from this class.
Definition at line 48 of file ProjectionHandler.cc.
References ProjectionHandler::clear().
00048 { 00049 clear(); 00050 }
ProjectionHandler | ( | const ProjectionHandler & | ) | [private] |
The copy constructor is hidden.
ProjectionHandler | ( | ) | [inline, private] |
The standard constructor.
Definition at line 91 of file ProjectionHandler.hh.
Referenced by ProjectionHandler::create().
ProjectionHandler& operator= | ( | const ProjectionHandler & | ) | [private] |
The assignment operator is hidden.
ProjectionHandler * create | ( | ) | [static] |
Singleton creation function.
Definition at line 18 of file ProjectionHandler.cc.
References ProjectionHandler::_instance, Log::getLog(), ProjectionHandler::ProjectionHandler(), and Log::TRACE.
00018 { 00019 if (!_instance) { 00020 _instance = new ProjectionHandler(); 00021 Log::getLog("Rivet.ProjectionHandler") 00022 << Log::TRACE << "Created new ProjectionHandler at " << _instance << endl; 00023 } 00024 return _instance; 00025 }
void destroy | ( | ) | [static] |
Singleton deletion function.
Definition at line 28 of file ProjectionHandler.cc.
References ProjectionHandler::_instance.
00028 { 00029 delete _instance; 00030 }
const Projection & registerProjection | ( | const ProjectionApplier & | parent, | |
const Projection & | proj, | |||
const string & | name | |||
) |
Attach and retrieve a projection as a reference.
Definition at line 57 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().
00060 { 00061 getLog() << Log::TRACE << "Trying to register" 00062 << " projection " << &proj << " (" << proj.name() << ")" 00063 << " for parent " << &parent << " (" << parent.name() << ")" 00064 << " with name '" << name << "'" << endl; 00065 00066 // Check for duplicate use of "name" on "parent" 00067 const bool dupOk = _checkDuplicate(parent, proj, name); 00068 if (!dupOk) exit(1); 00069 00070 // Choose which version of the projection to register with this parent and name 00071 const Projection* p = _getEquiv(proj); 00072 if (p == 0) { // a null pointer is a non-match 00073 // If there is no equivalent projection, clone proj and use the clone for registering 00074 p = _clone(proj); 00075 } 00076 00077 // Do the registering 00078 p = _register(parent, *p, name); 00079 00080 // Return registered proj 00081 return *p; 00082 }
const Projection * registerProjection | ( | const ProjectionApplier & | parent, | |
const Projection * | proj, | |||
const string & | name | |||
) |
Attach and retrieve a projection as a pointer.
Definition at line 88 of file ProjectionHandler.cc.
References ProjectionHandler::registerProjection().
00090 { 00091 if (proj == 0) return 0; 00092 const Projection& p = registerProjection(parent, *proj, name); 00093 return &p; 00094 }
const Projection * _getEquiv | ( | const Projection & | proj | ) | const [private] |
Try to get an equivalent projection from the system
Definition at line 146 of file ProjectionHandler.cc.
References ProjectionHandler::_projs, Rivet::EQUIVALENT, ProjectionHandler::getLog(), Projection::name(), Rivet::pcmp(), and Log::TRACE.
Referenced by ProjectionHandler::registerProjection().
00147 { 00148 // Get class type using RTTI 00149 const std::type_info& newtype = typeid(proj); 00150 getLog() << Log::TRACE << "RTTI type of " << &proj << " is " << newtype.name() << endl; 00151 00152 // Compare to ALL projections via _projs collection 00153 getLog() << Log::TRACE << "Comparing " << &proj 00154 << " with " << _projs.size() 00155 << " registered projection" << (_projs.size() == 1 ? "" : "s") << endl; 00156 foreach (const ProjHandle& ph, _projs) { 00157 // Make sure the concrete types match, using RTTI. 00158 const std::type_info& regtype = typeid(*ph); 00159 getLog() << Log::TRACE << "RTTI type comparison with " << ph << ": " 00160 << newtype.name() << " vs. " << regtype.name() << endl; 00161 if (newtype != regtype) continue; 00162 getLog() << Log::TRACE << "RTTI type matches with " << ph << endl; 00163 00164 // Test for semantic match 00165 if (pcmp(*ph, proj) != EQUIVALENT) { 00166 getLog() << Log::TRACE << "Projections at " 00167 << &proj << " and " << ph << " are not equivalent" << endl; 00168 } else { 00169 getLog() << Log::TRACE << "MATCH! Projections at " 00170 << &proj << " and " << ph << " are equivalent" << endl; 00171 return ph.get(); 00172 } 00173 } 00174 00175 // If no match, just return a null pointer 00176 return 0; 00177 }
const Projection * _clone | ( | const Projection & | proj | ) | [private] |
Make a clone of proj, copying across child references from the original.
Definition at line 99 of file ProjectionHandler.cc.
References ProjectionHandler::_namedprojs, Projection::clone(), ProjectionHandler::getLog(), Projection::name(), and Log::TRACE.
Referenced by ProjectionHandler::registerProjection().
00100 { 00101 // Clone a new copy of the passed projection on the heap 00102 getLog() << Log::TRACE << "Cloning projection " << proj.name() << " from " << &proj << endl; 00103 const Projection* newproj = proj.clone(); 00104 getLog() << Log::TRACE << "Cloned projection " << proj.name() << " at " << newproj << endl; 00105 getLog() << Log::TRACE << "Clone types " << typeid(proj).name() << " -> " << typeid(newproj).name() << endl; 00106 00107 // Copy all the child ProjHandles when cloning, since otherwise links to "stack parents" 00108 // will be generated by their children, without any connection to the cloned parent 00109 if (&proj != newproj) { 00110 NamedProjsMap::const_iterator nps = _namedprojs.find(&proj); 00111 if (nps != _namedprojs.end()) { 00112 getLog() << Log::TRACE << "Cloning registered projections list: " 00113 << &proj << " -> " << newproj << endl; 00114 _namedprojs[newproj] = nps->second; 00115 } 00116 } 00117 00118 return newproj; 00119 }
const Projection * _register | ( | const ProjectionApplier & | parent, | |
const Projection & | proj, | |||
const string & | name | |||
) | [private] |
Internal function to do the registering.
Definition at line 126 of file ProjectionHandler.cc.
References ProjectionHandler::_namedprojs, ProjectionHandler::_projs, ProjectionHandler::getLog(), and Log::TRACE.
Referenced by ProjectionHandler::registerProjection().
00129 { 00130 ProjHandle ph(&proj); 00131 getLog() << Log::TRACE << "Registering new projection at " << ph << endl; 00132 00133 // Add the passed Projection to _projs 00134 _projs.insert(ph); 00135 00136 // Add the ProjApplier* => name location to the associative container 00137 _namedprojs[&parent][name] = ph; 00138 00139 return ph.get(); 00140 }
string _getStatus | ( | ) | const [private] |
Get a string dump of the current ProjHandler structure.
Definition at line 181 of file ProjectionHandler.cc.
References ProjectionHandler::_namedprojs.
Referenced by ProjectionHandler::_checkDuplicate().
00181 { 00182 ostringstream msg; 00183 msg << "Current projection hierarchy:" << endl; 00184 foreach (const NamedProjsMap::value_type& nps, _namedprojs) { 00185 //const string parentname = nps.first->name(); 00186 msg << nps.first << endl; //"(" << parentname << ")" << endl; 00187 foreach (const NamedProjs::value_type& np, nps.second) { 00188 msg << " " << np.second << " (" << np.second->name() 00189 << ", locally called '" << np.first << "')" << endl; 00190 } 00191 msg << endl; 00192 } 00193 return msg.str(); 00194 }
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 199 of file ProjectionHandler.cc.
References ProjectionHandler::_getStatus(), ProjectionHandler::_namedprojs, Log::ERROR, ProjectionHandler::getLog(), Projection::name(), and ProjectionApplier::name().
Referenced by ProjectionHandler::registerProjection().
00202 { 00203 NamedProjsMap::const_iterator ipnps = _namedprojs.find(&parent); 00204 if (ipnps != _namedprojs.end()) { 00205 const NamedProjs pnps = ipnps->second; 00206 const NamedProjs::const_iterator ipph = pnps.find(name); 00207 if (ipph != pnps.end()) { 00208 const ProjHandle pph = ipph->second; 00209 getLog() << Log::ERROR << "Projection clash! " 00210 << parent.name() << " (" << &parent << ") " 00211 << "is trying to overwrite its registered '" << name << "' " 00212 << "projection (" << pph << "=" 00213 << pph->name() << ") with a non-equivalent projection " 00214 << "(" << &proj << "=" << proj.name() << ")" << endl; 00215 getLog() << Log::ERROR << _getStatus(); 00216 return false; 00217 } 00218 } 00219 return true; 00220 }
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 265 of file ProjectionHandler.cc.
References ProjectionHandler::_namedprojs.
Referenced by ProjectionApplier::getProjection().
00266 { 00267 //getLog() << Log::TRACE << "Searching for child projection '" 00268 // << name << "' of " << &parent << endl; 00269 NamedProjsMap::const_iterator nps = _namedprojs.find(&parent); 00270 if (nps == _namedprojs.end()) { 00271 ostringstream msg; 00272 msg << "No projections registered for parent " << &parent; 00273 throw Error(msg.str()); 00274 } 00275 NamedProjs::const_iterator np = nps->second.find(name); 00276 if (np == nps->second.end()) { 00277 ostringstream msg; 00278 msg << "No projection '" << name << "' found for parent " << &parent; 00279 throw Error(msg.str()); 00280 } 00281 // If it's registered with the projection handler, we must be able to safely 00282 // dereference the Projection pointer to a reference... 00283 return *(np->second); 00284 }
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 240 of file ProjectionHandler.cc.
References ProjectionHandler::_namedprojs, ProjectionHandler::DEEP, and ProjectionHandler::SHALLOW.
Referenced by ProjectionApplier::getProjections().
00242 { 00243 set<const Projection*> toplevel; 00244 NamedProjs nps = _namedprojs.find(&parent)->second; 00245 foreach (NamedProjs::value_type& np, nps) { 00246 toplevel.insert(np.second.get()); 00247 } 00248 if (depth == SHALLOW) { 00249 // Only return the projections directly contained within the top level 00250 return toplevel; 00251 } else { 00252 // Return recursively built projection list 00253 set<const Projection*> alllevels = toplevel; 00254 foreach (const Projection* p, toplevel) { 00255 set<const Projection*> allsublevels = getChildProjections(*p, DEEP); 00256 alllevels.insert(allsublevels.begin(), allsublevels.end()); 00257 } 00258 return alllevels; 00259 } 00260 }
void clear | ( | ) |
Projection clearing method: deletes all known projections and empties the reference collections.
Definition at line 40 of file ProjectionHandler.cc.
References ProjectionHandler::_namedprojs, and ProjectionHandler::_projs.
Referenced by ProjectionHandler::~ProjectionHandler().
00040 { 00041 _projs.clear(); 00042 _namedprojs.clear(); 00043 }
void removeProjectionApplier | ( | ProjectionApplier & | parent | ) | [private] |
Remove a ProjectionApplier: designed to only be called by ~ProjectionApplier (as a friend).
Definition at line 225 of file ProjectionHandler.cc.
References ProjectionHandler::_namedprojs, ProjectionHandler::_projs, and Rivet::pi.
Referenced by ProjectionApplier::~ProjectionApplier().
00225 { 00226 NamedProjsMap::iterator npi = _namedprojs.find(&parent); 00227 if (npi != _namedprojs.end()) _namedprojs.erase(npi); 00228 // 00229 const Projection* parentprojptr = dynamic_cast<Projection*>(&parent); 00230 if (parentprojptr) { 00231 ProjHandle parentph(parentprojptr); 00232 ProjHandles::iterator pi = find(_projs.begin(), _projs.end(), parentph); 00233 if (pi != _projs.end()) _projs.erase(pi); 00234 } 00235 }
Log & getLog | ( | ) | const [private] |
Get a logger.
Definition at line 34 of file ProjectionHandler.cc.
References Log::getLog().
Referenced by ProjectionHandler::_checkDuplicate(), ProjectionHandler::_clone(), ProjectionHandler::_getEquiv(), ProjectionHandler::_register(), and ProjectionHandler::registerProjection().
00034 { 00035 return Log::getLog("Rivet.ProjectionHandler"); 00036 }
friend class ProjectionApplier [friend] |
ProjectionApplier's destructor needs to trigger cleaning up the proj handler repo.
Definition at line 46 of file ProjectionHandler.hh.
NamedProjsMap _namedprojs [private] |
Core data member, associating a given containing class (via a ProjectionApplier pointer) to its contained projections.
Definition at line 67 of file ProjectionHandler.hh.
Referenced by ProjectionHandler::_checkDuplicate(), ProjectionHandler::_clone(), ProjectionHandler::_getStatus(), ProjectionHandler::_register(), ProjectionHandler::clear(), ProjectionHandler::getChildProjections(), ProjectionHandler::getProjection(), and ProjectionHandler::removeProjectionApplier().
ProjHandles _projs [private] |
Cache of Projections for reverse lookup, to speed up registering new projections as _namedprojs
gets large.
Definition at line 71 of file ProjectionHandler.hh.
Referenced by ProjectionHandler::_getEquiv(), ProjectionHandler::_register(), ProjectionHandler::clear(), and ProjectionHandler::removeProjectionApplier().
ProjectionHandler * _instance = 0 [static, private] |
Singleton instance
Definition at line 96 of file ProjectionHandler.hh.
Referenced by ProjectionHandler::create(), and ProjectionHandler::destroy().