Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-08-24 09:50:39

0001 #ifndef DataFormats_Common_Ptr_h
0002 #define DataFormats_Common_Ptr_h
0003 // -*- C++ -*-
0004 //
0005 // Package:     Common
0006 // Class  :     Ptr
0007 //
0008 /**\class edm::Ptr Ptr.h DataFormats/Common/interface/Ptr.h
0009 
0010  Description: Persistent 'pointer' to an item in a collection where the collection is in the edm::Event
0011 
0012  Usage:
0013     <usage>
0014 
0015 */
0016 //
0017 // Original Author:  Chris Jones
0018 //         Created:  Thu Oct 18 14:41:33 CEST 2007
0019 //
0020 
0021 // user include files
0022 #include "DataFormats/Common/interface/CMS_CLASS_VERSION.h"
0023 #include "DataFormats/Common/interface/WrapperBase.h"
0024 #include "DataFormats/Common/interface/EDProductGetter.h"
0025 #include "DataFormats/Common/interface/FillViewHelperVector.h"
0026 #include "DataFormats/Common/interface/GetProduct.h"
0027 #include "DataFormats/Common/interface/Handle.h"
0028 #include "DataFormats/Common/interface/OrphanHandle.h"
0029 #include "DataFormats/Common/interface/RefCore.h"
0030 #include "DataFormats/Common/interface/TestHandle.h"
0031 #include "DataFormats/Common/interface/traits.h"
0032 #include "DataFormats/Provenance/interface/ProductID.h"
0033 
0034 // system include files
0035 #include <type_traits>
0036 
0037 // forward declarations
0038 namespace edm {
0039   template <typename T>
0040   class Ptr {
0041     friend class PtrVectorBase;
0042 
0043   public:
0044     typedef unsigned long key_type;
0045     typedef T value_type;
0046 
0047     // General purpose constructor from handle.
0048     template <typename C>
0049     Ptr(Handle<C> const& handle, key_type itemKey, bool /*setNow*/ = true)
0050         : core_(handle.id(), getItem_(handle.product(), itemKey), nullptr, false), key_(itemKey) {}
0051 
0052     // General purpose constructor from orphan handle.
0053     template <typename C>
0054     Ptr(OrphanHandle<C> const& handle, key_type itemKey, bool /*setNow*/ = true)
0055         : core_(handle.id(), getItem_(handle.product(), itemKey), nullptr, false), key_(itemKey) {}
0056 
0057     // General purpose "constructor" from a Ref.
0058     // Use the conversion function template:
0059     // ptr = refToPtr(ref)
0060     // defined in DataFormats/Common/interface/RefToPtr.h
0061     // to construct a Ptr<T> from a Ref<C>, where T is C::value_type.
0062 
0063     // Constructors for ref to object that is not in an event.
0064     // An exception will be thrown if an attempt is made to persistify
0065     // any object containing this Ptr.  Also, in the future work will
0066     // be done to throw an exception if an attempt is made to put any object
0067     // containing this Ptr into an event(or run or lumi).
0068 
0069     template <typename C>
0070     Ptr(C const* iProduct, key_type iItemKey, bool /*setNow*/ = true)
0071         : core_(ProductID(), iProduct != nullptr ? getItem_(iProduct, iItemKey) : nullptr, nullptr, true),
0072           key_(iProduct != nullptr ? iItemKey : key_traits<key_type>::value) {}
0073 
0074     Ptr(T const* item, key_type iItemKey)
0075         : core_(ProductID(), item, nullptr, true), key_(item != nullptr ? iItemKey : key_traits<key_type>::value) {}
0076 
0077     // Constructor from test handle.
0078     // An exception will be thrown if an attempt is made to persistify
0079     // any object containing this Ptr.
0080     template <typename C>
0081     Ptr(TestHandle<C> const& handle, key_type itemKey, bool /*setNow*/ = true)
0082         : core_(handle.id(), getItem_(handle.product(), itemKey), nullptr, true), key_(itemKey) {}
0083 
0084     /** Constructor for those users who do not have a product handle,
0085      but have a pointer to a product getter (such as the EventPrincipal).
0086      prodGetter will ususally be a pointer to the event principal. */
0087     Ptr(ProductID const& productID, key_type itemKey, EDProductGetter const* prodGetter)
0088         : core_(productID, nullptr, mustBeNonZero(prodGetter, "Ptr", productID), false), key_(itemKey) {}
0089 
0090     /** Constructor for use in the various X::fillView(...) functions
0091      or for extracting a persistent Ptr from a PtrVector.
0092      It is an error (not diagnosable at compile- or run-time) to call
0093      this constructor with a pointer to a T unless the pointed-to T
0094      object is already in a collection of type C stored in the
0095      Event. The given ProductID must be the id of the collection
0096      in the Event. */
0097     Ptr(ProductID const& productID, T const* item, key_type item_key)
0098         : core_(productID, item, nullptr, false), key_(item_key) {}
0099 
0100     Ptr(ProductID const& productID, T const* item, key_type item_key, bool transient)
0101         : core_(productID, item, nullptr, transient), key_(item_key) {}
0102 
0103     /** Constructor that creates an invalid ("null") Ptr that is
0104      associated with a given product (denoted by that product's
0105      ProductID). */
0106 
0107     explicit Ptr(ProductID const& iId) : core_(iId, nullptr, nullptr, false), key_(key_traits<key_type>::value) {}
0108 
0109     Ptr() : core_(), key_(key_traits<key_type>::value) {}
0110 
0111     template <typename U>
0112       requires std::is_base_of_v<T, U>
0113     Ptr(Ptr<U> const& iOther)
0114         : core_(iOther.id(),
0115                 (iOther.hasProductCache() ? static_cast<T const*>(iOther.get()) : static_cast<T const*>(nullptr)),
0116                 iOther.productGetter(),
0117                 iOther.isTransient()),
0118           key_(iOther.key()) {
0119       //make sure a race condition didn't happen where between the call to hasProductCache() and
0120       // productGetter() the object was gotten
0121       if (iOther.hasProductCache() and not hasProductCache()) {
0122         core_.setProductPtr(static_cast<T const*>(iOther.get()));
0123       }
0124     }
0125 
0126     template <typename U>
0127       requires std::is_base_of_v<U, T>
0128     explicit Ptr(Ptr<U> const& iOther)
0129         : core_(iOther.id(), dynamic_cast<T const*>(iOther.get()), nullptr, iOther.isTransient()), key_(iOther.key()) {}
0130 
0131     /// Destructor
0132     ~Ptr() {}
0133 
0134     /// Dereference operator
0135     T const& operator*() const;
0136 
0137     /// Member dereference operator
0138     T const* operator->() const;
0139 
0140     /// Returns C++ pointer to the item
0141     T const* get() const { return isNull() ? nullptr : this->operator->(); }
0142 
0143     /// Checks for null
0144     bool isNull() const { return !isNonnull(); }
0145 
0146     /// Checks for non-null
0147     //bool isNonnull() const {return id().isValid(); }
0148     bool isNonnull() const { return key_traits<key_type>::value != key_; }
0149     /// Checks for null
0150     bool operator!() const { return isNull(); }
0151 
0152     /// Checks if collection is in memory or available
0153     /// in the event. No type checking is done.
0154     /// This function is potentially costly as it might cause a disk
0155     /// read (note that it does not cause the data to be cached locally)
0156     bool isAvailable() const;
0157 
0158     /// Checks if this Ptr is transient (i.e. not persistable).
0159     bool isTransient() const { return core_.isTransient(); }
0160 
0161     /// Accessor for product ID.
0162     ProductID id() const { return core_.id(); }
0163 
0164     /// Accessor for product getter.
0165     EDProductGetter const* productGetter() const { return core_.productGetter(); }
0166 
0167     key_type key() const { return key_; }
0168 
0169     bool hasProductCache() const { return nullptr != core_.productPtr(); }
0170 
0171     RefCore const& refCore() const { return core_; }
0172     // ---------- member functions ---------------------------
0173 
0174     void const* product() const { return nullptr; }
0175 
0176     //Used by ROOT storage
0177     CMS_CLASS_VERSION(10)
0178 
0179   private:
0180     template <typename C>
0181     T const* getItem_(C const* product, key_type iKey);
0182 
0183     void getData_(bool throwIfNotFound = true) const {
0184       EDProductGetter const* getter = productGetter();
0185       if (getter != nullptr) {
0186         WrapperBase const* prod = getter->getIt(core_.id());
0187         unsigned int iKey = key_;
0188         if (prod == nullptr) {
0189           auto optionalProd = getter->getThinnedProduct(core_.id(), key_);
0190           if (not optionalProd.has_value()) {
0191             if (throwIfNotFound) {
0192               core_.productNotFoundException(typeid(T));
0193             } else {
0194               return;
0195             }
0196           }
0197           std::tie(prod, iKey) = *optionalProd;
0198         }
0199         void const* ad = nullptr;
0200         prod->setPtr(typeid(T), iKey, ad);
0201         core_.setProductPtr(ad);
0202       }
0203     }
0204     // ---------- member data --------------------------------
0205     RefCore core_;
0206     key_type key_;
0207   };
0208 
0209   template <typename T>
0210   template <typename C>
0211   T const* Ptr<T>::getItem_(C const* iProduct, key_type iKey) {
0212     assert(iProduct != nullptr);
0213     typename C::const_iterator it = iProduct->begin();
0214     std::advance(it, iKey);
0215     T const* address = detail::GetProduct<C>::address(it);
0216     return address;
0217   }
0218 
0219   /// Dereference operator
0220   template <typename T>
0221   inline T const& Ptr<T>::operator*() const {
0222     getData_();
0223     return *reinterpret_cast<T const*>(core_.productPtr());
0224   }
0225 
0226   /// Member dereference operator
0227   template <typename T>
0228   inline T const* Ptr<T>::operator->() const {
0229     getData_();
0230     return reinterpret_cast<T const*>(core_.productPtr());
0231   }
0232 
0233   template <typename T>
0234   inline bool Ptr<T>::isAvailable() const {
0235     getData_(false);
0236     return hasProductCache();
0237   }
0238 
0239   template <typename T>
0240   inline bool operator==(Ptr<T> const& lhs, Ptr<T> const& rhs) {
0241     return lhs.refCore() == rhs.refCore() && lhs.key() == rhs.key();
0242   }
0243 
0244   template <typename T>
0245   inline bool operator!=(Ptr<T> const& lhs, Ptr<T> const& rhs) {
0246     return !(lhs == rhs);
0247   }
0248 
0249   template <typename T>
0250   inline bool operator<(Ptr<T> const& lhs, Ptr<T> const& rhs) {
0251     /// The ordering of integer keys guarantees that the ordering of Ptrs within
0252     /// a collection will be identical to the ordering of the referenced objects in the collection.
0253     return (lhs.refCore() == rhs.refCore() ? lhs.key() < rhs.key() : lhs.refCore() < rhs.refCore());
0254   }
0255 }  // namespace edm
0256 
0257 //The following is needed to get RefToBase to work with an edm::Ptr
0258 //Handle specialization here
0259 #include "DataFormats/Common/interface/HolderToVectorTrait_Ptr_specialization.h"
0260 #include <vector>
0261 
0262 namespace edm {
0263   template <typename T>
0264   inline void fillView(std::vector<edm::Ptr<T> > const& obj,
0265                        ProductID const& id,
0266                        std::vector<void const*>& pointers,
0267                        FillViewHelperVector& helpers) {
0268     pointers.reserve(obj.size());
0269     helpers.reserve(obj.size());
0270     for (auto const& p : obj) {
0271       if (p.isAvailable()) {
0272         pointers.push_back(p.get());
0273       } else {
0274         pointers.push_back(nullptr);
0275       }
0276       helpers.emplace_back(p.id(), p.key());
0277     }
0278   }
0279 }  // namespace edm
0280 
0281 #endif