Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-04-06 12:03:52

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     Ptr(Ptr<U> const& iOther, std::enable_if_t<std::is_base_of<T, U>::value>* = nullptr)
0113         : core_(iOther.id(),
0114                 (iOther.hasProductCache() ? static_cast<T const*>(iOther.get()) : static_cast<T const*>(nullptr)),
0115                 iOther.productGetter(),
0116                 iOther.isTransient()),
0117           key_(iOther.key()) {
0118       //make sure a race condition didn't happen where between the call to hasProductCache() and
0119       // productGetter() the object was gotten
0120       if (iOther.hasProductCache() and not hasProductCache()) {
0121         core_.setProductPtr(static_cast<T const*>(iOther.get()));
0122       }
0123     }
0124 
0125     template <typename U>
0126     explicit Ptr(Ptr<U> const& iOther, std::enable_if_t<std::is_base_of<U, T>::value>* = nullptr)
0127         : core_(iOther.id(), dynamic_cast<T const*>(iOther.get()), nullptr, iOther.isTransient()), key_(iOther.key()) {}
0128 
0129     /// Destructor
0130     ~Ptr() {}
0131 
0132     /// Dereference operator
0133     T const& operator*() const;
0134 
0135     /// Member dereference operator
0136     T const* operator->() const;
0137 
0138     /// Returns C++ pointer to the item
0139     T const* get() const { return isNull() ? nullptr : this->operator->(); }
0140 
0141     /// Checks for null
0142     bool isNull() const { return !isNonnull(); }
0143 
0144     /// Checks for non-null
0145     //bool isNonnull() const {return id().isValid(); }
0146     bool isNonnull() const { return key_traits<key_type>::value != key_; }
0147     /// Checks for null
0148     bool operator!() const { return isNull(); }
0149 
0150     /// Checks if collection is in memory or available
0151     /// in the event. No type checking is done.
0152     /// This function is potentially costly as it might cause a disk
0153     /// read (note that it does not cause the data to be cached locally)
0154     bool isAvailable() const;
0155 
0156     /// Checks if this Ptr is transient (i.e. not persistable).
0157     bool isTransient() const { return core_.isTransient(); }
0158 
0159     /// Accessor for product ID.
0160     ProductID id() const { return core_.id(); }
0161 
0162     /// Accessor for product getter.
0163     EDProductGetter const* productGetter() const { return core_.productGetter(); }
0164 
0165     key_type key() const { return key_; }
0166 
0167     bool hasProductCache() const { return nullptr != core_.productPtr(); }
0168 
0169     RefCore const& refCore() const { return core_; }
0170     // ---------- member functions ---------------------------
0171 
0172     void const* product() const { return nullptr; }
0173 
0174     //Used by ROOT storage
0175     CMS_CLASS_VERSION(10)
0176 
0177   private:
0178     template <typename C>
0179     T const* getItem_(C const* product, key_type iKey);
0180 
0181     void getData_(bool throwIfNotFound = true) const {
0182       EDProductGetter const* getter = productGetter();
0183       if (getter != nullptr) {
0184         WrapperBase const* prod = getter->getIt(core_.id());
0185         unsigned int iKey = key_;
0186         if (prod == nullptr) {
0187           auto optionalProd = getter->getThinnedProduct(core_.id(), key_);
0188           if (not optionalProd.has_value()) {
0189             if (throwIfNotFound) {
0190               core_.productNotFoundException(typeid(T));
0191             } else {
0192               return;
0193             }
0194           }
0195           std::tie(prod, iKey) = *optionalProd;
0196         }
0197         void const* ad = nullptr;
0198         prod->setPtr(typeid(T), iKey, ad);
0199         core_.setProductPtr(ad);
0200       }
0201     }
0202     // ---------- member data --------------------------------
0203     RefCore core_;
0204     key_type key_;
0205   };
0206 
0207   template <typename T>
0208   template <typename C>
0209   T const* Ptr<T>::getItem_(C const* iProduct, key_type iKey) {
0210     assert(iProduct != nullptr);
0211     typename C::const_iterator it = iProduct->begin();
0212     std::advance(it, iKey);
0213     T const* address = detail::GetProduct<C>::address(it);
0214     return address;
0215   }
0216 
0217   /// Dereference operator
0218   template <typename T>
0219   inline T const& Ptr<T>::operator*() const {
0220     getData_();
0221     return *reinterpret_cast<T const*>(core_.productPtr());
0222   }
0223 
0224   /// Member dereference operator
0225   template <typename T>
0226   inline T const* Ptr<T>::operator->() const {
0227     getData_();
0228     return reinterpret_cast<T const*>(core_.productPtr());
0229   }
0230 
0231   template <typename T>
0232   inline bool Ptr<T>::isAvailable() const {
0233     getData_(false);
0234     return hasProductCache();
0235   }
0236 
0237   template <typename T>
0238   inline bool operator==(Ptr<T> const& lhs, Ptr<T> const& rhs) {
0239     return lhs.refCore() == rhs.refCore() && lhs.key() == rhs.key();
0240   }
0241 
0242   template <typename T>
0243   inline bool operator!=(Ptr<T> const& lhs, Ptr<T> const& rhs) {
0244     return !(lhs == rhs);
0245   }
0246 
0247   template <typename T>
0248   inline bool operator<(Ptr<T> const& lhs, Ptr<T> const& rhs) {
0249     /// The ordering of integer keys guarantees that the ordering of Ptrs within
0250     /// a collection will be identical to the ordering of the referenced objects in the collection.
0251     return (lhs.refCore() == rhs.refCore() ? lhs.key() < rhs.key() : lhs.refCore() < rhs.refCore());
0252   }
0253 }  // namespace edm
0254 
0255 //The following is needed to get RefToBase to work with an edm::Ptr
0256 //Handle specialization here
0257 #include "DataFormats/Common/interface/HolderToVectorTrait_Ptr_specialization.h"
0258 #include <vector>
0259 
0260 namespace edm {
0261   template <typename T>
0262   inline void fillView(std::vector<edm::Ptr<T> > const& obj,
0263                        ProductID const& id,
0264                        std::vector<void const*>& pointers,
0265                        FillViewHelperVector& helpers) {
0266     pointers.reserve(obj.size());
0267     helpers.reserve(obj.size());
0268     for (auto const& p : obj) {
0269       if (p.isAvailable()) {
0270         pointers.push_back(p.get());
0271       } else {
0272         pointers.push_back(nullptr);
0273       }
0274       helpers.emplace_back(p.id(), p.key());
0275     }
0276   }
0277 }  // namespace edm
0278 
0279 #endif