Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2021-02-14 12:53:01

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     bool isAvailable() const;
0153 
0154     /// Checks if this Ptr is transient (i.e. not persistable).
0155     bool isTransient() const { return core_.isTransient(); }
0156 
0157     /// Accessor for product ID.
0158     ProductID id() const { return core_.id(); }
0159 
0160     /// Accessor for product getter.
0161     EDProductGetter const* productGetter() const { return core_.productGetter(); }
0162 
0163     key_type key() const { return key_; }
0164 
0165     bool hasProductCache() const { return nullptr != core_.productPtr(); }
0166 
0167     RefCore const& refCore() const { return core_; }
0168     // ---------- member functions ---------------------------
0169 
0170     void const* product() const { return nullptr; }
0171 
0172     //Used by ROOT storage
0173     CMS_CLASS_VERSION(10)
0174 
0175   private:
0176     template <typename C>
0177     T const* getItem_(C const* product, key_type iKey);
0178 
0179     void getData_(bool throwIfNotFound = true) const {
0180       EDProductGetter const* getter = productGetter();
0181       if (getter != nullptr) {
0182         WrapperBase const* prod = getter->getIt(core_.id());
0183         unsigned int iKey = key_;
0184         if (prod == nullptr) {
0185           auto optionalProd = getter->getThinnedProduct(core_.id(), key_);
0186           if (not optionalProd.has_value()) {
0187             if (throwIfNotFound) {
0188               core_.productNotFoundException(typeid(T));
0189             } else {
0190               return;
0191             }
0192           }
0193           std::tie(prod, iKey) = *optionalProd;
0194         }
0195         void const* ad = nullptr;
0196         prod->setPtr(typeid(T), iKey, ad);
0197         core_.setProductPtr(ad);
0198       }
0199     }
0200     // ---------- member data --------------------------------
0201     RefCore core_;
0202     key_type key_;
0203   };
0204 
0205   template <typename T>
0206   template <typename C>
0207   T const* Ptr<T>::getItem_(C const* iProduct, key_type iKey) {
0208     assert(iProduct != nullptr);
0209     typename C::const_iterator it = iProduct->begin();
0210     std::advance(it, iKey);
0211     T const* address = detail::GetProduct<C>::address(it);
0212     return address;
0213   }
0214 
0215   /// Dereference operator
0216   template <typename T>
0217   inline T const& Ptr<T>::operator*() const {
0218     getData_();
0219     return *reinterpret_cast<T const*>(core_.productPtr());
0220   }
0221 
0222   /// Member dereference operator
0223   template <typename T>
0224   inline T const* Ptr<T>::operator->() const {
0225     getData_();
0226     return reinterpret_cast<T const*>(core_.productPtr());
0227   }
0228 
0229   template <typename T>
0230   inline bool Ptr<T>::isAvailable() const {
0231     getData_(false);
0232     return hasProductCache();
0233   }
0234 
0235   template <typename T>
0236   inline bool operator==(Ptr<T> const& lhs, Ptr<T> const& rhs) {
0237     return lhs.refCore() == rhs.refCore() && lhs.key() == rhs.key();
0238   }
0239 
0240   template <typename T>
0241   inline bool operator!=(Ptr<T> const& lhs, Ptr<T> const& rhs) {
0242     return !(lhs == rhs);
0243   }
0244 
0245   template <typename T>
0246   inline bool operator<(Ptr<T> const& lhs, Ptr<T> const& rhs) {
0247     /// The ordering of integer keys guarantees that the ordering of Ptrs within
0248     /// a collection will be identical to the ordering of the referenced objects in the collection.
0249     return (lhs.refCore() == rhs.refCore() ? lhs.key() < rhs.key() : lhs.refCore() < rhs.refCore());
0250   }
0251 }  // namespace edm
0252 
0253 //The following is needed to get RefToBase to work with an edm::Ptr
0254 //Handle specialization here
0255 #include "DataFormats/Common/interface/HolderToVectorTrait_Ptr_specialization.h"
0256 #include <vector>
0257 
0258 namespace edm {
0259   template <typename T>
0260   inline void fillView(std::vector<edm::Ptr<T> > const& obj,
0261                        ProductID const& id,
0262                        std::vector<void const*>& pointers,
0263                        FillViewHelperVector& helpers) {
0264     pointers.reserve(obj.size());
0265     helpers.reserve(obj.size());
0266     for (auto const& p : obj) {
0267       if (p.isAvailable()) {
0268         pointers.push_back(p.get());
0269       } else {
0270         pointers.push_back(nullptr);
0271       }
0272       helpers.emplace_back(p.id(), p.key());
0273     }
0274   }
0275 }  // namespace edm
0276 
0277 #endif