File indexing completed on 2024-04-06 12:03:55
0001 #include "DataFormats/Common/interface/RefCore.h"
0002 #include "DataFormats/Common/interface/WrapperBase.h"
0003 #include "DataFormats/Common/interface/EDProductGetter.h"
0004 #include "FWCore/Utilities/interface/EDMException.h"
0005 #include "FWCore/Utilities/interface/TypeID.h"
0006 #include <cassert>
0007
0008 static void throwInvalidRefFromNullOrInvalidRef(const edm::TypeID& id) {
0009 throw edm::Exception(edm::errors::InvalidReference, "BadRefCore")
0010 << "RefCore: Request to resolve a null or invalid reference to a product of type '" << id
0011 << "' has been detected.\n"
0012 << "Please modify the calling code to test validity before dereferencing.\n";
0013 }
0014
0015 static void throwInvalidRefFromNoCache(const edm::TypeID& id, edm::ProductID const& prodID) {
0016 throw edm::Exception(edm::errors::InvalidReference, "BadRefCore")
0017 << "RefCore: A request to resolve a reference to a product of type '" << id << "' with ProductID '" << prodID
0018 << "' cannot be satisfied.\n"
0019 << "The reference has neither a valid product pointer nor an EDProductGetter.\n"
0020 << "The calling code must be modified to establish a functioning EDProducterGetter\n"
0021 << "for the context in which this call is mode\n";
0022 }
0023
0024 namespace edm {
0025
0026 RefCore::RefCore(ProductID const& theId, void const* prodPtr, EDProductGetter const* prodGetter, bool transient)
0027 : cachePtr_(prodPtr), processIndex_(theId.processIndex()), productIndex_(theId.productIndex()) {
0028 if (transient) {
0029 setTransient();
0030 }
0031 if (prodPtr == nullptr && prodGetter != nullptr) {
0032 setCacheIsProductGetter(prodGetter);
0033 }
0034 }
0035
0036 RefCore::RefCore(RefCore const& iOther) : processIndex_(iOther.processIndex_), productIndex_(iOther.productIndex_) {
0037 cachePtr_.store(iOther.cachePtr_.load(std::memory_order_relaxed), std::memory_order_relaxed);
0038 }
0039
0040 RefCore& RefCore::operator=(RefCore const& iOther) {
0041 cachePtr_.store(iOther.cachePtr_.load(std::memory_order_relaxed), std::memory_order_relaxed);
0042 processIndex_ = iOther.processIndex_;
0043 productIndex_ = iOther.productIndex_;
0044 return *this;
0045 }
0046
0047 WrapperBase const* RefCore::getProductPtr(std::type_info const& type, EDProductGetter const* prodGetter) const {
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062 ProductID tId = id();
0063 assert(!isTransient());
0064 if (!tId.isValid()) {
0065 throwInvalidRefFromNullOrInvalidRef(TypeID(type));
0066 }
0067
0068
0069 if (cachePtrIsInvalid()) {
0070 throwInvalidRefFromNoCache(TypeID(type), tId);
0071 }
0072 WrapperBase const* product = prodGetter->getIt(tId);
0073 if (product == nullptr) {
0074 productNotFoundException(type);
0075 }
0076 if (!(type == product->dynamicTypeInfo())) {
0077 wrongTypeException(type, product->dynamicTypeInfo());
0078 }
0079 return product;
0080 }
0081
0082 WrapperBase const* RefCore::tryToGetProductPtr(std::type_info const& type, EDProductGetter const* prodGetter) const {
0083 ProductID tId = id();
0084 assert(!isTransient());
0085 if (!tId.isValid()) {
0086 throwInvalidRefFromNullOrInvalidRef(TypeID(type));
0087 }
0088
0089 if (cachePtrIsInvalid()) {
0090 throwInvalidRefFromNoCache(TypeID(type), tId);
0091 }
0092 WrapperBase const* product = prodGetter->getIt(tId);
0093 if (product != nullptr && !(type == product->dynamicTypeInfo())) {
0094 wrongTypeException(type, product->dynamicTypeInfo());
0095 }
0096 return product;
0097 }
0098
0099 std::tuple<WrapperBase const*, unsigned int> RefCore::getThinnedProductPtr(std::type_info const& type,
0100 unsigned int key,
0101 EDProductGetter const* prodGetter) const {
0102 ProductID tId = id();
0103 std::optional product = prodGetter->getThinnedProduct(tId, key);
0104
0105 if (not product.has_value()) {
0106 productNotFoundException(type);
0107 }
0108 WrapperBase const* wrapper = std::get<WrapperBase const*>(*product);
0109 if (!(type == wrapper->dynamicTypeInfo())) {
0110 wrongTypeException(type, wrapper->dynamicTypeInfo());
0111 }
0112 return *product;
0113 }
0114
0115 bool RefCore::isThinnedAvailable(unsigned int key, EDProductGetter const* prodGetter) const {
0116 ProductID tId = id();
0117 if (!tId.isValid() || prodGetter == nullptr) {
0118
0119 return nullptr != productPtr();
0120 }
0121 std::optional product = prodGetter->getThinnedProduct(tId, key);
0122 return product.has_value();
0123 }
0124
0125 void RefCore::productNotFoundException(std::type_info const& type) const {
0126 throw edm::Exception(errors::ProductNotFound)
0127 << "RefCore: A request to resolve a reference to a product of type '" << TypeID(type) << "' with ProductID '"
0128 << id() << "'"
0129 << "\ncan not be satisfied because the product cannot be found."
0130 << "\nProbably the branch containing the product is not stored in the input file.\n";
0131 }
0132
0133 void RefCore::wrongTypeException(std::type_info const& expectedType, std::type_info const& actualType) const {
0134 throw edm::Exception(errors::InvalidReference, "WrongType")
0135 << "RefCore: A request to convert a contained product of type '" << TypeID(actualType) << "'\n"
0136 << " to type '" << TypeID(expectedType) << "'"
0137 << "\nfor ProductID '" << id() << "' can not be satisfied\n";
0138 }
0139
0140 void RefCore::nullPointerForTransientException(std::type_info const& type) const {
0141 throw edm::Exception(errors::InvalidReference)
0142 << "RefCore: A request to resolve a transient reference to a product of type: " << TypeID(type)
0143 << "\ncan not be satisfied because the pointer to the product is null.\n";
0144 }
0145
0146 bool RefCore::isAvailable() const {
0147 ProductID tId = id();
0148
0149
0150
0151 auto prodGetter = productGetter();
0152 auto prodPtr = productPtr();
0153 return prodPtr != nullptr || (tId.isValid() && prodGetter != nullptr && prodGetter->getIt(tId) != nullptr);
0154 }
0155
0156 void RefCore::setProductGetter(EDProductGetter const* prodGetter) const { setCacheIsProductGetter(prodGetter); }
0157
0158 void RefCore::setId(ProductID const& iId) {
0159 unsigned short head = processIndex_ & (refcoreimpl::kTransientBit | refcoreimpl::kCacheIsProductPtrBit);
0160 processIndex_ = iId.processIndex();
0161 processIndex_ |= head;
0162 productIndex_ = iId.productIndex();
0163 }
0164
0165 void RefCore::pushBackItem(RefCore const& productToBeInserted, bool checkPointer) {
0166 if (productToBeInserted.isNull() && !productToBeInserted.isTransient()) {
0167 throw edm::Exception(errors::InvalidReference, "Inconsistency")
0168 << "RefCore::pushBackItem: Ref or Ptr has invalid (zero) product ID, so it cannot be added to RefVector "
0169 "(PtrVector). "
0170 << "id should be (" << id() << ")\n";
0171 }
0172 if (isNonnull()) {
0173 if (isTransient() != productToBeInserted.isTransient()) {
0174 if (productToBeInserted.isTransient()) {
0175 throw edm::Exception(errors::InvalidReference, "Inconsistency")
0176 << "RefCore::pushBackItem: Transient Ref or Ptr cannot be added to persistable RefVector (PtrVector). "
0177 << "id should be (" << id() << ")\n";
0178 } else {
0179 throw edm::Exception(errors::InvalidReference, "Inconsistency")
0180 << "RefCore::pushBackItem: Persistable Ref or Ptr cannot be added to transient RefVector (PtrVector). "
0181 << "id is (" << productToBeInserted.id() << ")\n";
0182 }
0183 }
0184 if (!productToBeInserted.isTransient() && id() != productToBeInserted.id()) {
0185 throw edm::Exception(errors::InvalidReference, "Inconsistency")
0186 << "RefCore::pushBackItem: Ref or Ptr is inconsistent with RefVector (PtrVector)"
0187 << "id = (" << productToBeInserted.id() << ") should be (" << id() << ")\n";
0188 }
0189 if (productToBeInserted.isTransient() && checkPointer && productToBeInserted.isNonnull() &&
0190 productToBeInserted != *this) {
0191 throw edm::Exception(errors::InvalidReference, "Inconsistency")
0192 << "RefCore::pushBackItem: Ref points into different collection than the RefVector.\n";
0193 }
0194 } else {
0195 if (productToBeInserted.isTransient()) {
0196 setTransient();
0197 }
0198 if (productToBeInserted.isNonnull()) {
0199 setId(productToBeInserted.id());
0200 }
0201 }
0202
0203
0204
0205 if (productPtr() == nullptr && productToBeInserted.productPtr() != nullptr) {
0206 setProductPtr(productToBeInserted.productPtr());
0207 } else {
0208 auto getter = productToBeInserted.productGetter();
0209 if (cachePtrIsInvalid() && getter != nullptr) {
0210 setProductGetter(getter);
0211 }
0212 }
0213 }
0214
0215 void RefCore::pushBackRefItem(RefCore const& productToBeInserted) {
0216 if (productToBeInserted.isNull() && !productToBeInserted.isTransient()) {
0217 throw edm::Exception(errors::InvalidReference, "Inconsistency")
0218 << "RefCore::pushBackRefItem: Ref has invalid (zero) product ID, so it cannot be added to RefVector."
0219 << "id should be (" << id() << ")\n";
0220 }
0221 if (isNonnull() || isTransient()) {
0222 if (isTransient() != productToBeInserted.isTransient()) {
0223 if (productToBeInserted.isTransient()) {
0224 throw edm::Exception(errors::InvalidReference, "Inconsistency")
0225 << "RefCore::pushBackRefItem: Transient Ref cannot be added to persistable RefVector. "
0226 << "id should be (" << id() << ")\n";
0227 } else {
0228 throw edm::Exception(errors::InvalidReference, "Inconsistency")
0229 << "RefCore::pushBackRefItem: Persistable Ref cannot be added to transient RefVector. "
0230 << "id is (" << productToBeInserted.id() << ")\n";
0231 }
0232 }
0233 if (!productToBeInserted.isTransient() && id() != productToBeInserted.id()) {
0234 throw edm::Exception(errors::InvalidReference, "Inconsistency")
0235 << "RefCore::pushBackRefItem: Ref is inconsistent with RefVector"
0236 << "id = (" << productToBeInserted.id() << ") should be (" << id() << ")\n";
0237 }
0238 } else {
0239 if (productToBeInserted.isTransient()) {
0240 setTransient();
0241 }
0242 if (productToBeInserted.isNonnull()) {
0243 setId(productToBeInserted.id());
0244 }
0245 }
0246 auto prodGetter = productToBeInserted.productGetter();
0247 if (productGetter() == nullptr && prodGetter != nullptr) {
0248 setProductGetter(prodGetter);
0249 }
0250 }
0251 }