ProjectionHandler.hh
Go to the documentation of this file.
00001 // -*- C++ -*- 00002 #ifndef RIVET_ProjectionHandler_HH 00003 #define RIVET_ProjectionHandler_HH 00004 00005 #include "Rivet/Rivet.hh" 00006 #include "Rivet/RivetBoost.hh" 00007 #include "Rivet/Tools/Logging.fhh" 00008 #include "Rivet/Projection.fhh" 00009 00010 namespace Rivet { 00011 00012 00013 /// Typedef for Projection (smart) pointer 00014 typedef shared_ptr<const Projection> ProjHandle; 00015 00016 // Forward declaration. 00017 class ProjectionApplier; 00018 00019 /// @brief The projection handler is a central repository for projections to be used 00020 /// in a Rivet analysis run. 00021 /// 00022 /// Without centralised projections, it can be hard to know which of an 00023 /// equivalent set of projections will be run on a particular event. In turn, 00024 /// this may mean that certain projections in the chain can go out of scope 00025 /// unexpectedly. There were originally also the issues that projections may 00026 /// need to be held as member pointers to an abstract base class, since 00027 /// post-construction setup is needed; that projections contained pointers to 00028 /// their own dependency chain, which could go out of scope; and that 00029 /// projection members could be modified after being applied to an event 00030 /// which, due to the caching model, would have unpredictable consequences. 00031 /// 00032 /// By centralising all the projections, these issues are eliminated, as well 00033 /// as allowing analysis classes to contain fewer data members (since 00034 /// projections are now better accessed by name than by storing a data member 00035 /// reference or pointer). 00036 /// 00037 /// The core of the ProjectionHandler design is that it is a singleton class, 00038 /// essentially a wrapper around a map of @c Projection*, indexed by a hash of 00039 /// the registering object and its local name for the registered projection. 00040 /// 00041 class ProjectionHandler { 00042 public: 00043 00044 /// ProjectionApplier's destructor needs to trigger cleaning up the proj handler repo 00045 friend class ProjectionApplier; 00046 00047 /// Typedef for a vector of Projection pointers. 00048 typedef set<ProjHandle> ProjHandles; 00049 00050 /// @brief Typedef for the structure used to contain named projections for a 00051 /// particular containing Analysis or Projection. 00052 typedef map<const string, ProjHandle> NamedProjs; 00053 00054 /// Enum to specify depth of projection search. 00055 enum ProjDepth { SHALLOW, DEEP }; 00056 00057 00058 private: 00059 00060 /// Structure used to map a containing Analysis or Projection to its set of 00061 /// contained projections. 00062 typedef map<const ProjectionApplier*, NamedProjs> NamedProjsMap; 00063 00064 /// Core data member, associating a given containing class (via a 00065 /// ProjectionApplier pointer) to its contained projections. 00066 NamedProjsMap _namedprojs; 00067 00068 /// Cache of {@link Projection}s for reverse lookup, to speed up registering 00069 /// new projections as @c _namedprojs gets large. 00070 ProjHandles _projs; 00071 00072 00073 private: 00074 00075 /// @name Construction. */ 00076 //@{ 00077 00078 /// Private destructor means no inheritance from this class. 00079 ~ProjectionHandler(); 00080 00081 /// The assignment operator is hidden. 00082 ProjectionHandler& operator=(const ProjectionHandler&); 00083 00084 /// The copy constructor is hidden. 00085 ProjectionHandler(const ProjectionHandler&); 00086 00087 /// The standard constructor. 00088 ProjectionHandler() { } 00089 00090 /// @todo Remove in favour of the static singleton function 00091 static ProjectionHandler* _instance; 00092 00093 //@} 00094 00095 00096 public: 00097 00098 /// Singleton creation function 00099 static ProjectionHandler& getInstance(); // { 00100 /// @todo This is a better form of singleton, which cleans up properly... but it can't 00101 /// yet be used as it highlights a projection memory problem. Please fix so we can use this! 00102 // static ProjectionHandler _instance; 00103 // return _instance; 00104 // } 00105 00106 00107 public: 00108 00109 /// @name Projection registration 00110 //@{ 00111 /// Attach and retrieve a projection as a reference. 00112 const Projection& registerProjection(const ProjectionApplier& parent, 00113 const Projection& proj, 00114 const string& name); 00115 00116 /// Attach and retrieve a projection as a pointer. 00117 const Projection* registerProjection(const ProjectionApplier& parent, 00118 const Projection* proj, 00119 const string& name); 00120 //@} 00121 00122 00123 private: 00124 00125 /// @name Projection registration internal helpers 00126 //@{ 00127 00128 /// Try to get an equivalent projection from the system 00129 /// @returns 0 if no equivalent projection found 00130 const Projection* _getEquiv(const Projection& proj) const; 00131 00132 /// Make a clone of proj, copying across child references from the original 00133 const Projection* _clone(const Projection& proj); 00134 00135 /// Internal function to do the registering 00136 const Projection* _register(const ProjectionApplier& parent, 00137 const Projection& proj, 00138 const string& name); 00139 00140 /// Get a string dump of the current ProjHandler structure 00141 string _getStatus() const; 00142 00143 /// Check that this parent projection doesn't already use this name 00144 bool _checkDuplicate(const ProjectionApplier& parent, 00145 const Projection& proj, 00146 const string& name) const; 00147 00148 //@} 00149 00150 00151 public: 00152 00153 /// @name Projection retrieval. */ 00154 //@{ 00155 00156 /// Retrieve a named projection for the given parent. Returning as a 00157 /// reference is partly to discourage ProjectionApplier classes from storing 00158 /// pointer members to the registered projections, since that can lead to 00159 /// problems and there is no need to do so. 00160 const Projection& getProjection(const ProjectionApplier& parent, 00161 const string& name) const; 00162 00163 /// Get child projections for the given parent. By default this will just 00164 /// return the projections directly contained by the @a parent, but the @a 00165 /// depth argument can be changed to do a deep retrieval, which will recurse 00166 /// through the whole projection chain. In this case, there is no protection 00167 /// against getting stuck in a circular projection dependency loop. 00168 set<const Projection*> getChildProjections(const ProjectionApplier& parent, 00169 ProjDepth depth=SHALLOW) const; 00170 //@} 00171 00172 00173 /// Projection clearing method: deletes all known projections and empties 00174 /// the reference collections. 00175 void clear(); 00176 00177 00178 private: 00179 00180 /// Remove a ProjectionApplier: designed to only be called by ~ProjectionApplier (as a friend) 00181 void removeProjectionApplier(ProjectionApplier& parent); 00182 00183 00184 private: 00185 00186 /// Get a logger. 00187 Log& getLog() const; 00188 00189 00190 // /// Get map of named projections belonging to @a parent. 00191 // /// Throws an exception if @a parent has not got any registered projections. 00192 // const NamedProjs& namedProjs(const ProjectionApplier* parent) const { 00193 // NamedProjsMap::const_iterator nps = _namedprojs.find(parent); 00194 // if (nps == _namedprojs.end()) { 00195 // stringstream ss; 00196 // ss << "No NamedProjs registered for parent " << parent; 00197 // throw Error(ss.str()); 00198 // } 00199 // return *nps; 00200 // } 00201 00202 00203 }; 00204 00205 00206 } 00207 00208 #endif Generated on Fri Dec 21 2012 15:03:42 for The Rivet MC analysis system by ![]() |