Back to home page

Project CMSSW displayed by LXR

 
 

    


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

0001 #ifndef DataFormats_Common_RefItemGet_h
0002 #define DataFormats_Common_RefItemGet_h
0003 
0004 /*----------------------------------------------------------------------
0005   
0006 RefItemGet: Free function to get pointer to a referenced item.
0007 
0008 
0009 ----------------------------------------------------------------------*/
0010 #include "DataFormats/Common/interface/EDProductGetter.h"
0011 #include "DataFormats/Common/interface/RefCore.h"
0012 #include "DataFormats/Common/interface/RefCoreGet.h"
0013 
0014 namespace edm {
0015 
0016   namespace refitem {
0017 
0018     template <typename C, typename T, typename F, typename K>
0019     inline void findRefItem(RefCore const& refCore, C const* container, K const& key) {
0020       F finder;
0021       T const* item = finder(*container, key);
0022       refCore.setProductPtr(item);
0023     }
0024 
0025     template <typename C, typename T, typename F, typename KEY>
0026     struct GetRefPtrImpl {
0027       static T const* getRefPtr_(RefCore const& product, KEY const& key) {
0028         T const* item = static_cast<T const*>(product.productPtr());
0029         if (item != nullptr) {
0030           return item;
0031         }
0032         auto prodGetter = product.productGetter();
0033         if (nullptr == prodGetter) {
0034           item = static_cast<T const*>(product.productPtr());
0035           if (item != nullptr) {
0036             //Another thread updated the value since we checked
0037             return item;
0038           }
0039         }
0040         C const* prod = edm::template getProductWithCoreFromRef<C>(product, prodGetter);
0041         /*
0042         typename C::const_iterator it = prod->begin();
0043          std::advance(it, item.key());
0044          T const* p = it.operator->();
0045         */
0046         F func;
0047         item = func(*prod, key);
0048         product.setProductPtr(item);
0049         return item;
0050       }
0051     };
0052 
0053     template <typename C, typename T, typename F>
0054     struct GetRefPtrImpl<C, T, F, unsigned int> {
0055       static T const* getRefPtr_(RefCore const& product, unsigned int key) {
0056         T const* item = static_cast<T const*>(product.productPtr());
0057         if (item != nullptr) {
0058           return item;
0059         }
0060         auto getter = product.productGetter();
0061         if (getter == nullptr) {
0062           auto prod = product.productPtr();
0063           if (prod != nullptr) {
0064             //another thread updated the value since we last checked.
0065             return static_cast<T const*>(prod);
0066           }
0067         }
0068         C const* prod = edm::template tryToGetProductWithCoreFromRef<C>(product, getter);
0069         if (prod != nullptr) {
0070           F func;
0071           item = func(*prod, key);
0072           product.setProductPtr(item);
0073           return item;
0074         }
0075         unsigned int thinnedKey;
0076         std::tie(prod, thinnedKey) = edm::template getThinnedProduct<C>(product, key, getter);
0077         F func;
0078         item = func(*prod, thinnedKey);
0079         product.setProductPtr(item);
0080         return item;
0081       }
0082     };
0083   }  // namespace refitem
0084 
0085   template <typename C, typename T, typename F, typename KEY>
0086   inline T const* getRefPtr(RefCore const& product, KEY const& iKey) {
0087     return refitem::GetRefPtrImpl<C, T, F, KEY>::getRefPtr_(product, iKey);
0088   }
0089 
0090   namespace refitem {
0091     template <typename C, typename KEY>
0092     struct IsThinnedAvailableImpl {
0093       static bool isThinnedAvailable_(RefCore const& product, KEY const& key) { return false; }
0094     };
0095 
0096     template <typename C>
0097     struct IsThinnedAvailableImpl<C, unsigned int> {
0098       static bool isThinnedAvailable_(RefCore const& ref, unsigned int key) {
0099         if (ref.productPtr() != nullptr) {
0100           return true;
0101         }
0102         if (ref.isTransient()) {
0103           return false;
0104         }
0105         auto getter = ref.productGetter();
0106         if (getter != nullptr) {
0107           return ref.isThinnedAvailable(key, getter);
0108         }
0109         //another thread may have updated the cache
0110         return nullptr != ref.productPtr();
0111       }
0112     };
0113   }  // namespace refitem
0114 
0115   template <typename C, typename KEY>
0116   inline bool isThinnedAvailable(RefCore const& product, KEY const& iKey) {
0117     return refitem::IsThinnedAvailableImpl<C, KEY>::isThinnedAvailable_(product, iKey);
0118   }
0119 
0120   /// Return a Ref to thinned collection corresponding to an element of the Ref to parent collection
0121   //
0122   // The thinned may point to parent collection, in which case the Ref-to-parent is returned
0123   //
0124   // If thinned does not contain the element of the Ref-to-parent, a Null Ref is returned.
0125   //
0126   // If parent collection is not thinned, or there is no thinning relation between parent and thinned,
0127   // an exception is thrown
0128   template <typename C, typename T, typename F>
0129   Ref<C, T, F> thinnedRefFrom(Ref<C, T, F> const& parent,
0130                               RefProd<C> const& thinned,
0131                               edm::EDProductGetter const& prodGetter) {
0132     if (parent.id() == thinned.id()) {
0133       return parent;
0134     }
0135 
0136     auto thinnedKey = prodGetter.getThinnedKeyFrom(parent.id(), parent.key(), thinned.id());
0137     if (std::holds_alternative<unsigned int>(thinnedKey)) {
0138       return Ref<C, T, F>(thinned, std::get<unsigned int>(thinnedKey));
0139     } else if (std::holds_alternative<detail::GetThinnedKeyFromExceptionFactory>(thinnedKey)) {
0140       auto ex = std::get<detail::GetThinnedKeyFromExceptionFactory>(thinnedKey)();
0141       ex.addContext("Calling edm::thinnedRefFrom()");
0142       throw ex;
0143     }
0144 
0145     return Ref<C, T, F>();
0146   }
0147 
0148   /// Return a Ref to thinned collection corresponding to an element of the Ref to parent collection
0149   //
0150   // The thinned may point to parent collection, in which case the Ref-to-parent is returned
0151   //
0152   // If thinned does not contain the element of the Ref-to-parent, a Null Ref is returned.
0153   //
0154   // If parent collection is not thinned, or there is no thinning relation between parent and thinned,
0155   // a Null Ref is returned
0156   template <typename C, typename T, typename F>
0157   Ref<C, T, F> tryThinnedRefFrom(Ref<C, T, F> const& parent,
0158                                  RefProd<C> const& thinned,
0159                                  edm::EDProductGetter const& prodGetter) {
0160     if (parent.id() == thinned.id()) {
0161       return parent;
0162     }
0163 
0164     auto thinnedKey = prodGetter.getThinnedKeyFrom(parent.id(), parent.key(), thinned.id());
0165     if (std::holds_alternative<unsigned int>(thinnedKey)) {
0166       return Ref<C, T, F>(thinned, std::get<unsigned int>(thinnedKey));
0167     }
0168 
0169     return Ref<C, T, F>();
0170   }
0171 }  // namespace edm
0172 
0173 #endif