Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2021-12-14 11:45:05

0001 #ifndef FWCore_Framework_EventSetupRecord_h
0002 #define FWCore_Framework_EventSetupRecord_h
0003 // -*- C++ -*-
0004 //
0005 // Package:     Framework
0006 // Class  :     EventSetupRecord
0007 //
0008 /**\class edm::eventsetup::EventSetupRecord
0009 
0010  Description: Base class for all Records in an EventSetup.  A record is associated
0011  with data with the same lifetime.
0012 
0013  Usage:
0014 
0015  This class contains the interface that clients of the EventSetup
0016  use to get data associated with a record.
0017 
0018  This class holds a pointer to an EventSetupRecordImpl class, which
0019  is the class used to get the DataProxies associated with a given Record.
0020  It also has a pointer to the EventSetupImpl which is used to lookup
0021  dependent records in DependentRecordImplementation.
0022 
0023  It is important for the management of the Records that each Record
0024  know the ValidityInterval that represents the time over which its
0025  data is valid. The ValidityInterval is set by its EventSetupRecordProvider
0026  using the 'set' function.  This quantity can be recovered
0027  through the 'validityInterval' method.
0028 
0029  Most of the time one uses a record obtained from an EventSetup object
0030  and in that case the pointers this contains will be properly initialized
0031  automatically. If you construct a record object directly (usually using
0032  a type derived from this), then only a very limited subset of functions
0033  can be called because most of the member functions will dereference one
0034  of the null pointers and seg fault.
0035 */
0036 //
0037 // Author:      Chris Jones
0038 // Created:     Fri Mar 25 14:38:35 EST 2005
0039 //
0040 
0041 // user include files
0042 #include "FWCore/Framework/interface/FunctorESHandleExceptionFactory.h"
0043 #include "FWCore/Framework/interface/DataKey.h"
0044 #include "FWCore/Framework/interface/NoProxyException.h"
0045 #include "FWCore/Framework/interface/ValidityInterval.h"
0046 #include "FWCore/Framework/interface/EventSetupRecordImpl.h"
0047 #include "FWCore/Utilities/interface/ESGetToken.h"
0048 #include "FWCore/Utilities/interface/ESGetTokenGeneric.h"
0049 #include "FWCore/Utilities/interface/ESInputTag.h"
0050 #include "FWCore/Utilities/interface/ESIndices.h"
0051 #include "FWCore/Utilities/interface/Likely.h"
0052 #include "FWCore/Utilities/interface/deprecated_macro.h"
0053 
0054 // system include files
0055 #include <exception>
0056 #include <map>
0057 #include <memory>
0058 #include <utility>
0059 #include <vector>
0060 #include <atomic>
0061 #include <cassert>
0062 #include <limits>
0063 
0064 // forward declarations
0065 namespace cms {
0066   class Exception;
0067 }
0068 
0069 class testEventsetup;
0070 class testEventsetupRecord;
0071 
0072 namespace edm {
0073   template <typename T>
0074   class ESHandle;
0075   class ESHandleExceptionFactory;
0076   class ESInputTag;
0077   class EventSetupImpl;
0078 
0079   namespace eventsetup {
0080     struct ComponentDescription;
0081     class DataProxy;
0082     class EventSetupRecordKey;
0083 
0084     class EventSetupRecord {
0085     public:
0086       EventSetupRecord();
0087       EventSetupRecord(EventSetupRecord&&) = default;
0088       EventSetupRecord& operator=(EventSetupRecord&&) = default;
0089 
0090       EventSetupRecord(EventSetupRecord const&) = default;
0091       EventSetupRecord& operator=(EventSetupRecord const&) = default;
0092       virtual ~EventSetupRecord();
0093 
0094       // ---------- const member functions ---------------------
0095       ValidityInterval validityInterval() const { return impl_->validityInterval(); }
0096 
0097       void setImpl(EventSetupRecordImpl const* iImpl,
0098                    unsigned int transitionID,
0099                    ESProxyIndex const* getTokenIndices,
0100                    EventSetupImpl const* iEventSetupImpl,
0101                    ESParentContext const* iContext) {
0102         impl_ = iImpl;
0103         transitionID_ = transitionID;
0104         getTokenIndices_ = getTokenIndices;
0105         eventSetupImpl_ = iEventSetupImpl;
0106         context_ = iContext;
0107       }
0108 
0109       template <typename HolderT>
0110       CMS_DEPRECATED bool get(HolderT& iHolder) const {
0111         return deprecated_get("", iHolder);
0112       }
0113 
0114       template <typename HolderT>
0115       CMS_DEPRECATED bool get(char const* iName, HolderT& iHolder) const {
0116         return deprecated_get(iName, iHolder);
0117       }
0118 
0119       template <typename HolderT>
0120       CMS_DEPRECATED bool get(std::string const& iName, HolderT& iHolder) const {
0121         return deprecated_get(iName.c_str(), iHolder);
0122       }
0123 
0124       template <typename HolderT>
0125       CMS_DEPRECATED bool get(ESInputTag const& iTag, HolderT& iHolder) const {
0126         throwCalledGetWithoutToken(heterocontainer::className<typename HolderT::value_type>(), iTag.data().c_str());
0127         return false;
0128       }
0129 
0130       ///returns false if no data available for key
0131       bool doGet(ESGetTokenGeneric const&, bool aGetTransiently = false) const;
0132 
0133       /**returns true only if someone has already requested data for this key
0134           and the data was retrieved
0135           */
0136       bool wasGotten(DataKey const& aKey) const;
0137 
0138       /**returns the ComponentDescription for the module which creates the data or 0
0139           if no module has been registered for the data. This does not cause the data to
0140           actually be constructed.
0141           */
0142       ComponentDescription const* providerDescription(DataKey const& aKey) const;
0143 
0144       virtual EventSetupRecordKey key() const = 0;
0145 
0146       /**If you are caching data from the Record, you should also keep
0147           this number.  If this number changes then you know that
0148           the data you have cached is invalid. This is NOT true if
0149           if the validityInterval() hasn't changed since it is possible that
0150           the job has gone to a new Record and then come back to the
0151           previous SyncValue and your algorithm didn't see the intervening
0152           Record.
0153           The value of '0' will never be returned so you can use that to
0154           denote that you have not yet checked the value.
0155           */
0156       unsigned long long cacheIdentifier() const { return impl_->cacheIdentifier(); }
0157 
0158       /**When you are processing multiple validity intervals concurrently,
0159           each must have its own cache for data. These caches are numbered
0160           from 0 to one less than the maximum number of concurrent validity
0161           intervals allowed for that record. This number is returned by
0162           the following function. For one record type, all the different validity
0163           intervals being processed at the same time will have a different
0164           iovIndex. But the iovIndex's of record types that are different
0165           are independent of each other.
0166           */
0167       unsigned int iovIndex() const { return impl_->iovIndex(); }
0168 
0169       ///clears the oToFill vector and then fills it with the keys for all registered data keys
0170       void fillRegisteredDataKeys(std::vector<DataKey>& oToFill) const { impl_->fillRegisteredDataKeys(oToFill); }
0171 
0172       ///Classes that derive from EventSetupRecord can redefine this with a false value
0173       static constexpr bool allowConcurrentIOVs_ = true;
0174 
0175       friend class ::testEventsetup;
0176       friend class ::testEventsetupRecord;
0177 
0178     protected:
0179       template <template <typename> typename H, typename T, typename R>
0180       H<T> getHandleImpl(ESGetToken<T, R> const& iToken) const {
0181         if UNLIKELY (not iToken.isInitialized()) {
0182           std::rethrow_exception(makeUninitializedTokenException(this->key(), DataKey::makeTypeTag<T>()));
0183         }
0184         if UNLIKELY (iToken.transitionID() != transitionID()) {
0185           throwWrongTransitionID();
0186         }
0187         assert(getTokenIndices_);
0188         //need to check token has valid index
0189         if UNLIKELY (not iToken.hasValidIndex()) {
0190           return invalidTokenHandle<H>(iToken);
0191         }
0192 
0193         auto proxyIndex = getTokenIndices_[iToken.index().value()];
0194         if UNLIKELY (proxyIndex.value() == std::numeric_limits<int>::max()) {
0195           return noProxyHandle<H>(iToken);
0196         }
0197 
0198         T const* value = nullptr;
0199         ComponentDescription const* desc = nullptr;
0200         std::shared_ptr<ESHandleExceptionFactory> whyFailedFactory;
0201 
0202         impl_->getImplementation(value, proxyIndex, H<T>::transientAccessOnly, desc, whyFailedFactory, eventSetupImpl_);
0203 
0204         if UNLIKELY (not value) {
0205           return H<T>(std::move(whyFailedFactory));
0206         }
0207         return H<T>(value, desc);
0208       }
0209 
0210       EventSetupImpl const& eventSetup() const noexcept { return *eventSetupImpl_; }
0211 
0212       ESProxyIndex const* getTokenIndices() const noexcept { return getTokenIndices_; }
0213 
0214       ESParentContext const* esParentContext() const noexcept { return context_; }
0215 
0216       void validate(ComponentDescription const*, ESInputTag const&) const;
0217 
0218       void addTraceInfoToCmsException(cms::Exception& iException,
0219                                       char const* iName,
0220                                       ComponentDescription const*,
0221                                       DataKey const&) const;
0222 
0223       EventSetupRecordImpl const* impl() const { return impl_; }
0224 
0225       unsigned int transitionID() const { return transitionID_; }
0226 
0227     private:
0228       template <typename HolderT>
0229       bool deprecated_get(char const* iName, HolderT& iHolder) const {
0230         throwCalledGetWithoutToken(heterocontainer::className<typename HolderT::value_type>(), iName);
0231         return false;
0232       }
0233 
0234       template <template <typename> typename H, typename T, typename R>
0235       H<T> invalidTokenHandle(ESGetToken<T, R> const& iToken) const {
0236         auto const key = this->key();
0237         return H<T>{makeESHandleExceptionFactory([key, transitionID = iToken.transitionID()] {
0238           return makeInvalidTokenException(key, DataKey::makeTypeTag<T>(), transitionID);
0239         })};
0240       }
0241 
0242       template <template <typename> typename H, typename T, typename R>
0243       H<T> noProxyHandle(ESGetToken<T, R> const& iToken) const {
0244         auto const key = this->key();
0245         auto name = iToken.name();
0246         return H<T>{makeESHandleExceptionFactory([key, name] {
0247           NoProxyException<T> ex(key, DataKey{DataKey::makeTypeTag<T>(), name});
0248           return std::make_exception_ptr(ex);
0249         })};
0250       }
0251 
0252       void const* getFromProxy(DataKey const& iKey,
0253                                ComponentDescription const*& iDesc,
0254                                bool iTransientAccessOnly) const;
0255 
0256       static std::exception_ptr makeUninitializedTokenException(EventSetupRecordKey const&, TypeTag const&);
0257       static std::exception_ptr makeInvalidTokenException(EventSetupRecordKey const&, TypeTag const&, unsigned int);
0258       void throwWrongTransitionID() const;
0259       static void throwCalledGetWithoutToken(const char* iTypeName, const char* iLabel);
0260       // ---------- member data --------------------------------
0261       EventSetupRecordImpl const* impl_ = nullptr;
0262       EventSetupImpl const* eventSetupImpl_ = nullptr;
0263       ESProxyIndex const* getTokenIndices_ = nullptr;
0264       ESParentContext const* context_ = nullptr;
0265       unsigned int transitionID_ = std::numeric_limits<unsigned int>::max();
0266     };
0267 
0268     class EventSetupRecordGeneric : public EventSetupRecord {
0269     public:
0270       EventSetupRecordGeneric(EventSetupRecordImpl const* iImpl,
0271                               unsigned int iTransitionID,
0272                               ESProxyIndex const* getTokenIndices,
0273                               EventSetupImpl const* eventSetupImpl,
0274                               ESParentContext const* context) {
0275         setImpl(iImpl, iTransitionID, getTokenIndices, eventSetupImpl, context);
0276       }
0277 
0278       EventSetupRecordKey key() const final { return impl()->key(); }
0279     };
0280   }  // namespace eventsetup
0281 }  // namespace edm
0282 #endif