Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-10-07 04:59:29

0001 // -*- C++ -*-
0002 #ifndef FWCore_Framework_EventSetupRecord_h
0003 #define FWCore_Framework_EventSetupRecord_h
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 ESProductResolvers 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/HCTypeTag.h"
0045 #include "FWCore/Framework/interface/NoProductResolverException.h"
0046 #include "FWCore/Framework/interface/ValidityInterval.h"
0047 #include "FWCore/Framework/interface/EventSetupRecordImpl.h"
0048 #include "FWCore/Utilities/interface/ESGetToken.h"
0049 #include "FWCore/Utilities/interface/ESGetTokenGeneric.h"
0050 #include "FWCore/Utilities/interface/ESIndices.h"
0051 #include "FWCore/Utilities/interface/Likely.h"
0052 
0053 // system include files
0054 #include <exception>
0055 #include <memory>
0056 #include <utility>
0057 #include <vector>
0058 #include <cassert>
0059 #include <limits>
0060 
0061 // forward declarations
0062 namespace cms {
0063   class Exception;
0064 }
0065 
0066 class testEventsetup;
0067 class testEventsetupRecord;
0068 
0069 namespace edm {
0070   class ESHandleExceptionFactory;
0071   class ESParentContext;
0072   class EventSetupImpl;
0073 
0074   namespace eventsetup {
0075     struct ComponentDescription;
0076     class EventSetupRecordKey;
0077 
0078     class EventSetupRecord {
0079     public:
0080       EventSetupRecord();
0081       EventSetupRecord(EventSetupRecord&&) = default;
0082       EventSetupRecord& operator=(EventSetupRecord&&) = default;
0083 
0084       EventSetupRecord(EventSetupRecord const&) = default;
0085       EventSetupRecord& operator=(EventSetupRecord const&) = default;
0086       virtual ~EventSetupRecord();
0087 
0088       // ---------- const member functions ---------------------
0089       ValidityInterval validityInterval() const { return impl_->validityInterval(); }
0090 
0091       void setImpl(EventSetupRecordImpl const* iImpl,
0092                    unsigned int transitionID,
0093                    ESResolverIndex const* getTokenIndices,
0094                    EventSetupImpl const* iEventSetupImpl,
0095                    ESParentContext const* iContext) {
0096         impl_ = iImpl;
0097         transitionID_ = transitionID;
0098         getTokenIndices_ = getTokenIndices;
0099         eventSetupImpl_ = iEventSetupImpl;
0100         context_ = iContext;
0101       }
0102 
0103       ///returns false if no data available for key
0104       bool doGet(ESGetTokenGeneric const&, bool aGetTransiently = false) const;
0105 
0106       /**returns true only if someone has already requested data for this key
0107           and the data was retrieved
0108           */
0109       bool wasGotten(DataKey const& aKey) const;
0110 
0111       /**returns the ComponentDescription for the module which creates the data or 0
0112           if no module has been registered for the data. This does not cause the data to
0113           actually be constructed.
0114           */
0115       ComponentDescription const* providerDescription(DataKey const& aKey) const;
0116 
0117       virtual EventSetupRecordKey key() const = 0;
0118 
0119       /**If you are caching data from the Record, you should also keep
0120           this number.  If this number changes then you know that
0121           the data you have cached is invalid. This is NOT true if
0122           if the validityInterval() hasn't changed since it is possible that
0123           the job has gone to a new Record and then come back to the
0124           previous SyncValue and your algorithm didn't see the intervening
0125           Record.
0126           The value of '0' will never be returned so you can use that to
0127           denote that you have not yet checked the value.
0128           */
0129       unsigned long long cacheIdentifier() const { return impl_->cacheIdentifier(); }
0130 
0131       /**When you are processing multiple validity intervals concurrently,
0132           each must have its own cache for data. These caches are numbered
0133           from 0 to one less than the maximum number of concurrent validity
0134           intervals allowed for that record. This number is returned by
0135           the following function. For one record type, all the different validity
0136           intervals being processed at the same time will have a different
0137           iovIndex. But the iovIndex's of record types that are different
0138           are independent of each other.
0139           */
0140       unsigned int iovIndex() const { return impl_->iovIndex(); }
0141 
0142       ///clears the oToFill vector and then fills it with the keys for all registered data keys
0143       void fillRegisteredDataKeys(std::vector<DataKey>& oToFill) const { impl_->fillRegisteredDataKeys(oToFill); }
0144 
0145       ///Classes that derive from EventSetupRecord can redefine this with a false value
0146       static constexpr bool allowConcurrentIOVs_ = true;
0147 
0148       friend class ::testEventsetup;
0149       friend class ::testEventsetupRecord;
0150 
0151     protected:
0152       template <template <typename> typename H, typename T, typename R>
0153       H<T> getHandleImpl(ESGetToken<T, R> const& iToken) const {
0154         if UNLIKELY (not iToken.isInitialized()) {
0155           std::rethrow_exception(makeUninitializedTokenException(this->key(), DataKey::makeTypeTag<T>()));
0156         }
0157         if UNLIKELY (iToken.transitionID() != transitionID()) {
0158           throwWrongTransitionID();
0159         }
0160         assert(getTokenIndices_);
0161         //need to check token has valid index
0162         if UNLIKELY (not iToken.hasValidIndex()) {
0163           return invalidTokenHandle<H>(iToken);
0164         }
0165 
0166         auto resolverIndex = getTokenIndices_[iToken.index().value()];
0167 
0168         if UNLIKELY (resolverIndex == ESResolverIndex::moduleLabelDoesNotMatch()) {
0169           return noResolverHandle<H>(iToken, true);
0170         }
0171 
0172         if UNLIKELY (resolverIndex == ESResolverIndex::noResolverConfigured()) {
0173           return noResolverHandle<H>(iToken, false);
0174         }
0175 
0176         T const* value = nullptr;
0177         ComponentDescription const* desc = nullptr;
0178         std::shared_ptr<ESHandleExceptionFactory> whyFailedFactory;
0179 
0180         impl_->getImplementation(value, resolverIndex, H<T>::transientAccessOnly, desc, whyFailedFactory);
0181 
0182         if UNLIKELY (not value) {
0183           return H<T>(std::move(whyFailedFactory));
0184         }
0185         return H<T>(value, desc);
0186       }
0187 
0188       EventSetupImpl const& eventSetup() const noexcept { return *eventSetupImpl_; }
0189 
0190       ESResolverIndex const* getTokenIndices() const noexcept { return getTokenIndices_; }
0191 
0192       ESParentContext const* esParentContext() const noexcept { return context_; }
0193 
0194       void addTraceInfoToCmsException(cms::Exception& iException,
0195                                       char const* iName,
0196                                       ComponentDescription const*,
0197                                       DataKey const&) const;
0198 
0199       EventSetupRecordImpl const* impl() const { return impl_; }
0200 
0201       unsigned int transitionID() const { return transitionID_; }
0202 
0203     private:
0204       template <template <typename> typename H, typename T, typename R>
0205       H<T> invalidTokenHandle(ESGetToken<T, R> const& iToken) const {
0206         auto const key = this->key();
0207         return H<T>{makeESHandleExceptionFactory([key, transitionID = iToken.transitionID()] {
0208           return makeInvalidTokenException(key, DataKey::makeTypeTag<T>(), transitionID);
0209         })};
0210       }
0211 
0212       template <template <typename> typename H, typename T, typename R>
0213       H<T> noResolverHandle(ESGetToken<T, R> const& iToken, bool moduleLabelDoesNotMatch) const {
0214         auto const key = this->key();
0215         auto productLabel = iToken.productLabel();
0216         return H<T>{makeESHandleExceptionFactory([key, productLabel, moduleLabelDoesNotMatch] {
0217           NoProductResolverException ex(key, heterocontainer::className<T>(), productLabel, moduleLabelDoesNotMatch);
0218           return std::make_exception_ptr(ex);
0219         })};
0220       }
0221 
0222       static std::exception_ptr makeUninitializedTokenException(EventSetupRecordKey const&, TypeTag const&);
0223       static std::exception_ptr makeInvalidTokenException(EventSetupRecordKey const&, TypeTag const&, unsigned int);
0224       void throwWrongTransitionID() const;
0225 
0226       // ---------- member data --------------------------------
0227       EventSetupRecordImpl const* impl_ = nullptr;
0228       EventSetupImpl const* eventSetupImpl_ = nullptr;
0229       ESResolverIndex const* getTokenIndices_ = nullptr;
0230       ESParentContext const* context_ = nullptr;
0231       unsigned int transitionID_ = std::numeric_limits<unsigned int>::max();
0232     };
0233 
0234     class EventSetupRecordGeneric : public EventSetupRecord {
0235     public:
0236       EventSetupRecordGeneric(EventSetupRecordImpl const* iImpl,
0237                               unsigned int iTransitionID,
0238                               ESResolverIndex const* getTokenIndices,
0239                               EventSetupImpl const* eventSetupImpl,
0240                               ESParentContext const* context) {
0241         setImpl(iImpl, iTransitionID, getTokenIndices, eventSetupImpl, context);
0242       }
0243 
0244       EventSetupRecordKey key() const final { return impl()->key(); }
0245     };
0246   }  // namespace eventsetup
0247 }  // namespace edm
0248 #endif