CMS 3D CMS Logo

RefCore.cc
Go to the documentation of this file.
6 #include <cassert>
7 
8 static
11  "BadRefCore")
12  << "RefCore: Request to resolve a null or invalid reference to a product of type '"
13  << id
14  << "' has been detected.\n"
15  << "Please modify the calling code to test validity before dereferencing.\n";
16 }
17 
18 static
19 void throwInvalidRefFromNoCache(const edm::TypeID& id, edm::ProductID const& prodID) {
21  "BadRefCore")
22  << "RefCore: A request to resolve a reference to a product of type '"
23  << id
24  << "' with ProductID '" << prodID
25  << "' cannot be satisfied.\n"
26  << "The reference has neither a valid product pointer nor an EDProductGetter.\n"
27  << "The calling code must be modified to establish a functioning EDProducterGetter\n"
28  << "for the context in which this call is mode\n";
29 
30 }
31 
32 namespace edm {
33 
34  RefCore::RefCore(ProductID const& theId, void const* prodPtr, EDProductGetter const* prodGetter, bool transient) :
35  cachePtr_(prodPtr),
36  processIndex_(theId.processIndex()),
37  productIndex_(theId.productIndex())
38  {
39  if(transient) {
40  setTransient();
41  }
42  if(prodPtr==nullptr && prodGetter!=nullptr) {
43  setCacheIsProductGetter(prodGetter);
44  }
45  }
46 
47  RefCore::RefCore( RefCore const& iOther) :
50  cachePtr_.store(iOther.cachePtr_.load(std::memory_order_relaxed), std::memory_order_relaxed);
51  }
52 
53  RefCore& RefCore::operator=( RefCore const& iOther) {
54  cachePtr_.store(iOther.cachePtr_.load(std::memory_order_relaxed), std::memory_order_relaxed);
57  return *this;
58  }
59 
60  WrapperBase const*
61  RefCore::getProductPtr(std::type_info const& type, EDProductGetter const* prodGetter) const {
62  // The following invariant would be nice to establish in all
63  // constructors, but we can not be sure that the context in which
64  // EDProductGetter::instance() is called will be one where a
65  // non-null pointer is returned. The biggest question in the
66  // various times at which Root makes RefCore instances, and how
67  // old ones might be recycled.
68  //
69  // If our ProductID is non-null, we must have a way to get at the
70  // product (unless it has been dropped). This means either we
71  // already have the pointer to the product, or we have a valid
72  // EDProductGetter to use.
73  //
74  // assert(!id_.isValid() || productGetter() || prodPtr_);
75 
76  ProductID tId = id();
77  assert (!isTransient());
78  if (!tId.isValid()) {
80  }
81 
82  //if (productPtr() == 0 && productGetter() == 0) {
83  if (cachePtrIsInvalid()) {
85  }
86  WrapperBase const* product = prodGetter->getIt(tId);
87  if (product == nullptr) {
89  }
90  if(!(type == product->dynamicTypeInfo())) {
91  wrongTypeException(type, product->dynamicTypeInfo());
92  }
93  return product;
94  }
95 
96  WrapperBase const*
97  RefCore::tryToGetProductPtr(std::type_info const& type, EDProductGetter const* prodGetter) const {
98  ProductID tId = id();
99  assert (!isTransient());
100  if (!tId.isValid()) {
102  }
103 
104  if (cachePtrIsInvalid()) {
106  }
107  WrapperBase const* product = prodGetter->getIt(tId);
108  if(product != nullptr && !(type == product->dynamicTypeInfo())) {
109  wrongTypeException(type, product->dynamicTypeInfo());
110  }
111  return product;
112  }
113 
114  WrapperBase const*
115  RefCore::getThinnedProductPtr(std::type_info const& type, unsigned int& thinnedKey, EDProductGetter const* prodGetter) const {
116 
117  ProductID tId = id();
118  WrapperBase const* product = prodGetter->getThinnedProduct(tId, thinnedKey);
119 
120  if (product == nullptr) {
122  }
123  if(!(type == product->dynamicTypeInfo())) {
124  wrongTypeException(type, product->dynamicTypeInfo());
125  }
126  return product;
127  }
128 
129  bool
130  RefCore::isThinnedAvailable(unsigned int thinnedKey, EDProductGetter const* prodGetter) const {
131  ProductID tId = id();
132  if(!tId.isValid() || prodGetter == nullptr) {
133  //another thread may have changed it
134  return nullptr != productPtr();
135  }
136  WrapperBase const* product = prodGetter->getThinnedProduct(tId, thinnedKey);
137  return product != nullptr;
138  }
139 
140  void
141  RefCore::productNotFoundException(std::type_info const& type) const {
143  << "RefCore: A request to resolve a reference to a product of type '"
144  << TypeID(type)
145  << "' with ProductID '" << id() << "'"
146  << "\ncan not be satisfied because the product cannot be found."
147  << "\nProbably the branch containing the product is not stored in the input file.\n";
148  }
149 
150  void
151  RefCore::wrongTypeException(std::type_info const& expectedType, std::type_info const& actualType) const {
152  throw edm::Exception(errors::InvalidReference,"WrongType")
153  << "RefCore: A request to convert a contained product of type '"
154  << TypeID(actualType) << "'\n"
155  << " to type '" << TypeID(expectedType) << "'"
156  << "\nfor ProductID '" << id()
157  << "' can not be satisfied\n";
158  }
159 
160  void
161  RefCore::nullPointerForTransientException(std::type_info const& type) const {
163  << "RefCore: A request to resolve a transient reference to a product of type: "
164  << TypeID(type)
165  << "\ncan not be satisfied because the pointer to the product is null.\n";
166  }
167 
168  bool
170  ProductID tId = id();
171  //If another thread changes the cache, it will change a non-null productGetter
172  // into a null productGeter but productPtr will be non-null
173  // Therefore reading productGetter() first is the safe order
174  auto prodGetter = productGetter();
175  auto prodPtr = productPtr();
176  return prodPtr != nullptr || (tId.isValid() && prodGetter != nullptr && prodGetter->getIt(tId) != nullptr);
177  }
178 
179  void
180  RefCore::setProductGetter(EDProductGetter const* prodGetter) const {
181  setCacheIsProductGetter(prodGetter);
182  }
183 
184  void
185  RefCore::setId(ProductID const& iId) {
187  processIndex_ = iId.processIndex();
188  processIndex_ |= head;
189  productIndex_ = iId.productIndex();
190  }
191 
192 
193  void
194  RefCore::pushBackItem(RefCore const& productToBeInserted, bool checkPointer) {
195  if (productToBeInserted.isNull() && !productToBeInserted.isTransient()) {
196  throw edm::Exception(errors::InvalidReference,"Inconsistency")
197  << "RefCore::pushBackItem: Ref or Ptr has invalid (zero) product ID, so it cannot be added to RefVector (PtrVector). "
198  << "id should be (" << id() << ")\n";
199  }
200  if (isNonnull()) {
201  if (isTransient() != productToBeInserted.isTransient()) {
202  if (productToBeInserted.isTransient()) {
203  throw edm::Exception(errors::InvalidReference,"Inconsistency")
204  << "RefCore::pushBackItem: Transient Ref or Ptr cannot be added to persistable RefVector (PtrVector). "
205  << "id should be (" << id() << ")\n";
206  } else {
207  throw edm::Exception(errors::InvalidReference,"Inconsistency")
208  << "RefCore::pushBackItem: Persistable Ref or Ptr cannot be added to transient RefVector (PtrVector). "
209  << "id is (" << productToBeInserted.id() << ")\n";
210  }
211  }
212  if (!productToBeInserted.isTransient() && id() != productToBeInserted.id()) {
213  throw edm::Exception(errors::InvalidReference,"Inconsistency")
214  << "RefCore::pushBackItem: Ref or Ptr is inconsistent with RefVector (PtrVector)"
215  << "id = (" << productToBeInserted.id() << ") should be (" << id() << ")\n";
216  }
217  if (productToBeInserted.isTransient() && checkPointer && productToBeInserted.isNonnull() && productToBeInserted != *this) {
218  throw edm::Exception(errors::InvalidReference,"Inconsistency")
219  << "RefCore::pushBackItem: Ref points into different collection than the RefVector.\n";
220  }
221  } else {
222  if (productToBeInserted.isTransient()) {
223  setTransient();
224  }
225  if (productToBeInserted.isNonnull()) {
226  setId(productToBeInserted.id());
227  }
228  }
229  //Since productPtr and productGetter actually share the same pointer internally,
230  // we want to be sure that if the productPtr is set we use that one and only if
231  // it isn't set do we set the productGetter if available
232  if (productPtr() == nullptr && productToBeInserted.productPtr() != nullptr) {
233  setProductPtr(productToBeInserted.productPtr());
234  } else {
235  auto getter = productToBeInserted.productGetter();
236  if (cachePtrIsInvalid() && getter != nullptr) {
237  setProductGetter(getter);
238  }
239  }
240  }
241 
242  void
243  RefCore::pushBackRefItem(RefCore const& productToBeInserted) {
244  if (productToBeInserted.isNull() && !productToBeInserted.isTransient()) {
245  throw edm::Exception(errors::InvalidReference,"Inconsistency")
246  << "RefCore::pushBackRefItem: Ref has invalid (zero) product ID, so it cannot be added to RefVector."
247  << "id should be (" << id() << ")\n";
248  }
249  if (isNonnull() || isTransient()) {
250  if (isTransient() != productToBeInserted.isTransient()) {
251  if (productToBeInserted.isTransient()) {
252  throw edm::Exception(errors::InvalidReference,"Inconsistency")
253  << "RefCore::pushBackRefItem: Transient Ref cannot be added to persistable RefVector. "
254  << "id should be (" << id() << ")\n";
255  } else {
256  throw edm::Exception(errors::InvalidReference,"Inconsistency")
257  << "RefCore::pushBackRefItem: Persistable Ref cannot be added to transient RefVector. "
258  << "id is (" << productToBeInserted.id() << ")\n";
259  }
260  }
261  if (!productToBeInserted.isTransient() && id() != productToBeInserted.id()) {
262  throw edm::Exception(errors::InvalidReference,"Inconsistency")
263  << "RefCore::pushBackRefItem: Ref is inconsistent with RefVector"
264  << "id = (" << productToBeInserted.id() << ") should be (" << id() << ")\n";
265  }
266  } else {
267  if (productToBeInserted.isTransient()) {
268  setTransient();
269  }
270  if (productToBeInserted.isNonnull()) {
271  setId(productToBeInserted.id());
272  }
273  }
274  auto prodGetter = productToBeInserted.productGetter();
275  if (productGetter() == nullptr && prodGetter != nullptr) {
276  setProductGetter(prodGetter);
277  }
278  }
279 }
void pushBackItem(RefCore const &productToBeInserted, bool checkPointer)
Definition: RefCore.cc:194
type
Definition: HCALResponse.h:21
void setProductPtr(void const *prodPtr) const
Definition: RefCore.h:58
std::type_info const & dynamicTypeInfo() const
Definition: WrapperBase.h:46
bool isThinnedAvailable(unsigned int thinnedKey, EDProductGetter const *prodGetter) const
Definition: RefCore.cc:130
virtual WrapperBase const * getThinnedProduct(ProductID const &, unsigned int &key) const =0
WrapperBase const * getProductPtr(std::type_info const &type, EDProductGetter const *prodGetter) const
Definition: RefCore.cc:61
ProcessIndex productIndex() const
Definition: ProductID.h:37
bool isNonnull() const
Definition: RefCore.h:74
WrapperBase const * tryToGetProductPtr(std::type_info const &type, EDProductGetter const *prodGetter) const
Definition: RefCore.cc:97
ProductIndex productIndex_
Definition: RefCore.h:133
bool cachePtrIsInvalid() const
Definition: RefCore.h:121
WrapperBase const * getThinnedProductPtr(std::type_info const &type, unsigned int &thinnedKey, EDProductGetter const *prodGetter) const
Definition: RefCore.cc:115
void const * productPtr() const
Definition: RefCore.h:52
bool isAvailable() const
Definition: RefCore.cc:169
virtual WrapperBase const * getIt(ProductID const &) const =0
void productNotFoundException(std::type_info const &type) const
Definition: RefCore.cc:141
ProcessIndex processIndex_
Definition: RefCore.h:132
bool isNull() const
Definition: RefCore.h:71
RefCore & operator=(RefCore const &)
Definition: RefCore.cc:53
static void throwInvalidRefFromNullOrInvalidRef(const edm::TypeID &id)
Definition: RefCore.cc:9
void setId(ProductID const &iId)
Definition: RefCore.cc:185
EDProductGetter const * productGetter() const
Definition: RefCore.h:84
ProductID id() const
Definition: RefCore.h:49
bool isTransient() const
Definition: RefCore.h:106
const std::uintptr_t kCacheIsProductPtrBit
std::atomic< void const * > cachePtr_
Definition: RefCore.h:126
HLT enums.
const unsigned short kTransientBit
static void throwInvalidRefFromNoCache(const edm::TypeID &id, edm::ProductID const &prodID)
Definition: RefCore.cc:19
void setProductGetter(EDProductGetter const *prodGetter) const
Definition: RefCore.cc:180
void pushBackRefItem(RefCore const &productToBeInserted)
Definition: RefCore.cc:243
void setCacheIsProductGetter(EDProductGetter const *iGetter) const
Definition: RefCore.h:120
bool isValid() const
Definition: ProductID.h:35
ProcessIndex processIndex() const
Definition: ProductID.h:36
void setTransient()
Definition: RefCore.h:118
void wrongTypeException(std::type_info const &expectedType, std::type_info const &actualType) const
Definition: RefCore.cc:151
void nullPointerForTransientException(std::type_info const &type) const
Definition: RefCore.cc:161