Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-04-19 09:06:57

0001 // -*- C++ -*-
0002 #ifndef RIVET_ProjectionHandler_HH
0003 #define RIVET_ProjectionHandler_HH
0004 
0005 // @todo all thread/mutex code belongs to a temporary fix to allow for
0006 // basic threading
0007 #include <thread>
0008 #include <mutex>
0009 #include "Rivet/Config/RivetCommon.hh"
0010 #include "Rivet/Projection.fhh"
0011 
0012 namespace Rivet {
0013 
0014 
0015   /// Typedef for Projection (smart) pointer
0016   typedef std::shared_ptr<const Projection> ProjHandle;
0017 
0018   // Forward declaration.
0019   class ProjectionApplier;
0020 
0021   /// @brief The projection handler is a central repository for projections to be used
0022   /// in a Rivet analysis run.
0023   ///
0024   /// Without centralised projections, it can be hard to know which of an
0025   /// equivalent set of projections will be run on a particular event. In turn,
0026   /// this may mean that certain projections in the chain can go out of scope
0027   /// unexpectedly. There were originally also the issues that projections may
0028   /// need to be held as member pointers to an abstract base class, since
0029   /// post-construction setup is needed; that projections contained pointers to
0030   /// their own dependency chain, which could go out of scope; and that
0031   /// projection members could be modified after being applied to an event
0032   /// which, due to the caching model, would have unpredictable consequences.
0033   ///
0034   /// By centralising all the projections, these issues are eliminated, as well
0035   /// as allowing analysis classes to contain fewer data members (since
0036   /// projections are now better accessed by name than by storing a data member
0037   /// reference or pointer).
0038   ///
0039   /// The core of the ProjectionHandler design is that it is a singleton class,
0040   /// essentially a wrapper around a map of @c Projection*, indexed by a hash of
0041   /// the registering object and its local name for the registered projection.
0042   ///
0043   class ProjectionHandler {
0044   public:
0045 
0046     /// ProjectionApplier's destructor needs to trigger cleaning up the proj handler repo
0047     friend class ProjectionApplier;
0048 
0049     /// Typedef for a vector of Projection pointers.
0050     typedef set<ProjHandle> ProjHandles;
0051 
0052     /// @brief Typedef for the structure used to contain named projections for a
0053     /// particular containing Analysis or Projection.
0054     typedef map<string, ProjHandle> NamedProjs;
0055 
0056     /// Enum to specify depth of projection search.
0057     enum ProjDepth { SHALLOW, DEEP };
0058 
0059 
0060   private:
0061 
0062     /// Structure used to map a containing Analysis or Projection to its set of
0063     /// contained projections.
0064     typedef map<const ProjectionApplier*, NamedProjs> NamedProjsMap;
0065 
0066     /// Core data member, associating a given containing class (via a
0067     /// ProjectionApplier pointer) to its contained projections.
0068     NamedProjsMap _namedprojs;
0069 
0070     /// Cache of {@link Projection}s for reverse lookup, to speed up registering
0071     /// new projections as @c _namedprojs gets large.
0072     ProjHandles _projs;
0073 
0074 
0075   public:
0076 
0077     /// @name Construction. */
0078     /// @{
0079 
0080     /// Private destructor means no inheritance from this class.
0081     ~ProjectionHandler() = default;
0082 
0083     /// The assignment operator is hidden.
0084     ProjectionHandler& operator = (const ProjectionHandler&) = delete;
0085 
0086     /// The copy constructor is hidden.
0087     ProjectionHandler(const ProjectionHandler&) = delete;
0088 
0089     /// The standard constructor.
0090     ProjectionHandler() = default;
0091 
0092   public:
0093 
0094     /// @name Projection registration
0095     /// @{
0096     /// Attach and retrieve a projection as a reference.
0097     const Projection& registerProjection(const ProjectionApplier& parent,
0098                                          const Projection& proj,
0099                                          const string& name);
0100     /// @}
0101 
0102 
0103   private:
0104 
0105     /// @name Projection registration internal helpers
0106     /// @{
0107 
0108     /// Try to get an equivalent projection from the system
0109     /// @returns 0 if no equivalent projection found
0110     ProjHandle _getEquiv(const Projection& proj) const;
0111 
0112     /// Make a clone of proj, copying across child references from the original
0113     unique_ptr<Projection> _clone(const Projection& proj);
0114 
0115     /// Internal function to do the registering
0116     const Projection& _register(const ProjectionApplier& parent,
0117                                 ProjHandle proj,
0118                                 const string& name);
0119 
0120     /// Get a string dump of the current ProjHandler structure
0121     string _getStatus() const;
0122 
0123     /// Check that this parent projection doesn't already use this name
0124     bool _checkDuplicate(const ProjectionApplier& parent,
0125                          const Projection& proj,
0126                          const string& name) const;
0127 
0128     /// @}
0129 
0130 
0131   public:
0132 
0133     /// @name Projection retrieval. */
0134     /// @{
0135 
0136     /// Check if there is a @a name projection registered by @a parent
0137     bool hasProjection(const ProjectionApplier& parent, const string& name) const;
0138 
0139     /// Retrieve a named projection for the given parent. Returning as a
0140     /// reference is partly to discourage ProjectionApplier classes from storing
0141     /// pointer members to the registered projections, since that can lead to
0142     /// problems and there is no need to do so.
0143     /// Does look in the declQueue, but NOT recursively (yet?).
0144     const Projection& getProjection(const ProjectionApplier& parent,
0145                                     const string& name) const;
0146 
0147     /// Get child projections for the given parent. By default this will just
0148     /// return the projections directly contained by the @a parent, but the @a
0149     /// depth argument can be changed to do a deep retrieval, which will recurse
0150     /// through the whole projection chain. In this case, there is no protection
0151     /// against getting stuck in a circular projection dependency loop.
0152     /// Does NOT look in declQueue
0153     set<const Projection*> getChildProjections(const ProjectionApplier& parent,
0154                                                ProjDepth depth=SHALLOW) const;
0155     /// @}
0156 
0157 
0158   private:
0159 
0160     /// Remove a ProjectionApplier: designed to only be called by ~ProjectionApplier (as a friend)
0161     void removeProjectionApplier(ProjectionApplier& parent);
0162 
0163 
0164   private:
0165 
0166     // /// Get map of named projections belonging to @a parent.
0167     // /// Throws an exception if @a parent has not got any registered projections.
0168     // const NamedProjs& namedProjs(const ProjectionApplier* parent) const {
0169     //   NamedProjsMap::const_iterator nps = _namedprojs.find(parent);
0170     //   if (nps == _namedprojs.end()) {
0171     //     stringstream ss;
0172     //     ss << "No NamedProjs registered for parent " << parent;
0173     //     throw Error(ss.str());
0174     //   }
0175     //   return *nps;
0176     // }
0177 
0178 
0179   };
0180 
0181 
0182 }
0183 
0184 #endif