1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
|
#ifndef DataFormats_Common_Ptr_h
#define DataFormats_Common_Ptr_h
// -*- C++ -*-
//
// Package: Common
// Class : Ptr
//
/**\class edm::Ptr Ptr.h DataFormats/Common/interface/Ptr.h
Description: Persistent 'pointer' to an item in a collection where the collection is in the edm::Event
Usage:
<usage>
*/
//
// Original Author: Chris Jones
// Created: Thu Oct 18 14:41:33 CEST 2007
//
// user include files
#include "DataFormats/Common/interface/CMS_CLASS_VERSION.h"
#include "DataFormats/Common/interface/WrapperBase.h"
#include "DataFormats/Common/interface/EDProductGetter.h"
#include "DataFormats/Common/interface/FillViewHelperVector.h"
#include "DataFormats/Common/interface/GetProduct.h"
#include "DataFormats/Common/interface/Handle.h"
#include "DataFormats/Common/interface/OrphanHandle.h"
#include "DataFormats/Common/interface/RefCore.h"
#include "DataFormats/Common/interface/TestHandle.h"
#include "DataFormats/Common/interface/traits.h"
#include "DataFormats/Provenance/interface/ProductID.h"
// system include files
#include <type_traits>
// forward declarations
namespace edm {
template <typename T>
class Ptr {
friend class PtrVectorBase;
public:
typedef unsigned long key_type;
typedef T value_type;
// General purpose constructor from handle.
template <typename C>
Ptr(Handle<C> const& handle, key_type itemKey, bool /*setNow*/ = true)
: core_(handle.id(), getItem_(handle.product(), itemKey), nullptr, false), key_(itemKey) {}
// General purpose constructor from orphan handle.
template <typename C>
Ptr(OrphanHandle<C> const& handle, key_type itemKey, bool /*setNow*/ = true)
: core_(handle.id(), getItem_(handle.product(), itemKey), nullptr, false), key_(itemKey) {}
// General purpose "constructor" from a Ref.
// Use the conversion function template:
// ptr = refToPtr(ref)
// defined in DataFormats/Common/interface/RefToPtr.h
// to construct a Ptr<T> from a Ref<C>, where T is C::value_type.
// Constructors for ref to object that is not in an event.
// An exception will be thrown if an attempt is made to persistify
// any object containing this Ptr. Also, in the future work will
// be done to throw an exception if an attempt is made to put any object
// containing this Ptr into an event(or run or lumi).
template <typename C>
Ptr(C const* iProduct, key_type iItemKey, bool /*setNow*/ = true)
: core_(ProductID(), iProduct != nullptr ? getItem_(iProduct, iItemKey) : nullptr, nullptr, true),
key_(iProduct != nullptr ? iItemKey : key_traits<key_type>::value) {}
Ptr(T const* item, key_type iItemKey)
: core_(ProductID(), item, nullptr, true), key_(item != nullptr ? iItemKey : key_traits<key_type>::value) {}
// Constructor from test handle.
// An exception will be thrown if an attempt is made to persistify
// any object containing this Ptr.
template <typename C>
Ptr(TestHandle<C> const& handle, key_type itemKey, bool /*setNow*/ = true)
: core_(handle.id(), getItem_(handle.product(), itemKey), nullptr, true), key_(itemKey) {}
/** Constructor for those users who do not have a product handle,
but have a pointer to a product getter (such as the EventPrincipal).
prodGetter will ususally be a pointer to the event principal. */
Ptr(ProductID const& productID, key_type itemKey, EDProductGetter const* prodGetter)
: core_(productID, nullptr, mustBeNonZero(prodGetter, "Ptr", productID), false), key_(itemKey) {}
/** Constructor for use in the various X::fillView(...) functions
or for extracting a persistent Ptr from a PtrVector.
It is an error (not diagnosable at compile- or run-time) to call
this constructor with a pointer to a T unless the pointed-to T
object is already in a collection of type C stored in the
Event. The given ProductID must be the id of the collection
in the Event. */
Ptr(ProductID const& productID, T const* item, key_type item_key)
: core_(productID, item, nullptr, false), key_(item_key) {}
Ptr(ProductID const& productID, T const* item, key_type item_key, bool transient)
: core_(productID, item, nullptr, transient), key_(item_key) {}
/** Constructor that creates an invalid ("null") Ptr that is
associated with a given product (denoted by that product's
ProductID). */
explicit Ptr(ProductID const& iId) : core_(iId, nullptr, nullptr, false), key_(key_traits<key_type>::value) {}
Ptr() : core_(), key_(key_traits<key_type>::value) {}
template <typename U>
requires std::is_base_of_v<T, U>
Ptr(Ptr<U> const& iOther)
: core_(iOther.id(),
(iOther.hasProductCache() ? static_cast<T const*>(iOther.get()) : static_cast<T const*>(nullptr)),
iOther.productGetter(),
iOther.isTransient()),
key_(iOther.key()) {
//make sure a race condition didn't happen where between the call to hasProductCache() and
// productGetter() the object was gotten
if (iOther.hasProductCache() and not hasProductCache()) {
core_.setProductPtr(static_cast<T const*>(iOther.get()));
}
}
template <typename U>
requires std::is_base_of_v<U, T>
explicit Ptr(Ptr<U> const& iOther)
: core_(iOther.id(), dynamic_cast<T const*>(iOther.get()), nullptr, iOther.isTransient()), key_(iOther.key()) {}
/// Destructor
~Ptr() {}
/// Dereference operator
T const& operator*() const;
/// Member dereference operator
T const* operator->() const;
/// Returns C++ pointer to the item
T const* get() const { return isNull() ? nullptr : this->operator->(); }
/// Checks for null
bool isNull() const { return !isNonnull(); }
/// Checks for non-null
//bool isNonnull() const {return id().isValid(); }
bool isNonnull() const { return key_traits<key_type>::value != key_; }
/// Checks for null
bool operator!() const { return isNull(); }
/// Checks if collection is in memory or available
/// in the event. No type checking is done.
/// This function is potentially costly as it might cause a disk
/// read (note that it does not cause the data to be cached locally)
bool isAvailable() const;
/// Checks if this Ptr is transient (i.e. not persistable).
bool isTransient() const { return core_.isTransient(); }
/// Accessor for product ID.
ProductID id() const { return core_.id(); }
/// Accessor for product getter.
EDProductGetter const* productGetter() const { return core_.productGetter(); }
key_type key() const { return key_; }
bool hasProductCache() const { return nullptr != core_.productPtr(); }
RefCore const& refCore() const { return core_; }
// ---------- member functions ---------------------------
void const* product() const { return nullptr; }
//Used by ROOT storage
CMS_CLASS_VERSION(10)
private:
template <typename C>
T const* getItem_(C const* product, key_type iKey);
void getData_(bool throwIfNotFound = true) const {
EDProductGetter const* getter = productGetter();
if (getter != nullptr) {
WrapperBase const* prod = getter->getIt(core_.id());
unsigned int iKey = key_;
if (prod == nullptr) {
auto optionalProd = getter->getThinnedProduct(core_.id(), key_);
if (not optionalProd.has_value()) {
if (throwIfNotFound) {
core_.productNotFoundException(typeid(T));
} else {
return;
}
}
std::tie(prod, iKey) = *optionalProd;
}
void const* ad = nullptr;
prod->setPtr(typeid(T), iKey, ad);
core_.setProductPtr(ad);
}
}
// ---------- member data --------------------------------
RefCore core_;
key_type key_;
};
template <typename T>
template <typename C>
T const* Ptr<T>::getItem_(C const* iProduct, key_type iKey) {
assert(iProduct != nullptr);
typename C::const_iterator it = iProduct->begin();
std::advance(it, iKey);
T const* address = detail::GetProduct<C>::address(it);
return address;
}
/// Dereference operator
template <typename T>
inline T const& Ptr<T>::operator*() const {
getData_();
return *reinterpret_cast<T const*>(core_.productPtr());
}
/// Member dereference operator
template <typename T>
inline T const* Ptr<T>::operator->() const {
getData_();
return reinterpret_cast<T const*>(core_.productPtr());
}
template <typename T>
inline bool Ptr<T>::isAvailable() const {
getData_(false);
return hasProductCache();
}
template <typename T>
inline bool operator==(Ptr<T> const& lhs, Ptr<T> const& rhs) {
return lhs.refCore() == rhs.refCore() && lhs.key() == rhs.key();
}
template <typename T>
inline bool operator!=(Ptr<T> const& lhs, Ptr<T> const& rhs) {
return !(lhs == rhs);
}
template <typename T>
inline bool operator<(Ptr<T> const& lhs, Ptr<T> const& rhs) {
/// The ordering of integer keys guarantees that the ordering of Ptrs within
/// a collection will be identical to the ordering of the referenced objects in the collection.
return (lhs.refCore() == rhs.refCore() ? lhs.key() < rhs.key() : lhs.refCore() < rhs.refCore());
}
} // namespace edm
//The following is needed to get RefToBase to work with an edm::Ptr
//Handle specialization here
#include "DataFormats/Common/interface/HolderToVectorTrait_Ptr_specialization.h"
#include <vector>
namespace edm {
template <typename T>
inline void fillView(std::vector<edm::Ptr<T> > const& obj,
ProductID const& id,
std::vector<void const*>& pointers,
FillViewHelperVector& helpers) {
pointers.reserve(obj.size());
helpers.reserve(obj.size());
for (auto const& p : obj) {
if (p.isAvailable()) {
pointers.push_back(p.get());
} else {
pointers.push_back(nullptr);
}
helpers.emplace_back(p.id(), p.key());
}
}
} // namespace edm
#endif
|