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