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     /// Singleton deletion function
00105     static void destroy();
00106 
00107 
00108   public:
00109 
00110     /// @name Projection registration
00111     //@{
00112     /// Attach and retrieve a projection as a reference.
00113     const Projection& registerProjection(const ProjectionApplier& parent,
00114                                          const Projection& proj,
00115                                          const string& name);
00116 
00117     /// Attach and retrieve a projection as a pointer.
00118     const Projection* registerProjection(const ProjectionApplier& parent,
00119                                          const Projection* proj,
00120                                          const string& name);
00121     //@}
00122 
00123 
00124   private:
00125 
00126     /// @name Projection registration internal helpers
00127     //@{
00128 
00129     /// Try to get an equivalent projection from the system
00130     /// @returns 0 if no equivalent projection found
00131     const Projection* _getEquiv(const Projection& proj) const;
00132 
00133     /// Make a clone of proj, copying across child references from the original
00134     const Projection* _clone(const Projection& proj);
00135 
00136     /// Internal function to do the registering
00137     const Projection* _register(const ProjectionApplier& parent,
00138                                 const Projection& proj,
00139                                 const string& name);
00140 
00141     /// Get a string dump of the current ProjHandler structure
00142     string _getStatus() const;
00143 
00144     /// Check that this parent projection doesn't already use this name
00145     bool _checkDuplicate(const ProjectionApplier& parent,
00146                          const Projection& proj,
00147                          const string& name) const;
00148 
00149     //@}
00150 
00151 
00152   public:
00153 
00154     /// @name Projection retrieval. */
00155     //@{
00156 
00157     /// Retrieve a named projection for the given parent. Returning as a
00158     /// reference is partly to discourage ProjectionApplier classes from storing
00159     /// pointer members to the registered projections, since that can lead to
00160     /// problems and there is no need to do so.
00161     const Projection& getProjection(const ProjectionApplier& parent,
00162                                     const string& name) const;
00163 
00164     /// Get child projections for the given parent. By default this will just
00165     /// return the projections directly contained by the @a parent, but the @a
00166     /// depth argument can be changed to do a deep retrieval, which will recurse
00167     /// through the whole projection chain. In this case, there is no protection
00168     /// against getting stuck in a circular projection dependency loop.
00169     set<const Projection*> getChildProjections(const ProjectionApplier& parent,
00170                                                ProjDepth depth=SHALLOW) const;
00171     //@}
00172 
00173 
00174     /// Projection clearing method: deletes all known projections and empties
00175     /// the reference collections.
00176     void clear();
00177 
00178 
00179   private:
00180 
00181     /// Remove a ProjectionApplier: designed to only be called by ~ProjectionApplier (as a friend)
00182     void removeProjectionApplier(ProjectionApplier& parent);
00183 
00184 
00185   private:
00186 
00187     /// Get a logger.
00188     Log& getLog() const;
00189 
00190 
00191     // /// Get map of named projections belonging to @a parent.
00192     // /// Throws an exception if @a parent has not got any registered projections.
00193     // const NamedProjs& namedProjs(const ProjectionApplier* parent) const {
00194     //   NamedProjsMap::const_iterator nps = _namedprojs.find(parent);
00195     //   if (nps == _namedprojs.end()) {
00196     //     stringstream ss;
00197     //     ss << "No NamedProjs registered for parent " << parent;
00198     //     throw Error(ss.str());
00199     //   }
00200     //   return *nps;
00201     // }
00202 
00203 
00204   };
00205 
00206 
00207 }
00208 
00209 #endif