Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2023-01-15 23:49:39

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