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
|
#ifndef DataFormats_Common_RefItemGet_h
#define DataFormats_Common_RefItemGet_h
/*----------------------------------------------------------------------
RefItemGet: Free function to get pointer to a referenced item.
----------------------------------------------------------------------*/
#include "DataFormats/Common/interface/EDProductGetter.h"
#include "DataFormats/Common/interface/RefCore.h"
#include "DataFormats/Common/interface/RefCoreGet.h"
namespace edm {
namespace refitem {
template <typename C, typename T, typename F, typename K>
inline void findRefItem(RefCore const& refCore, C const* container, K const& key) {
F finder;
T const* item = finder(*container, key);
refCore.setProductPtr(item);
}
template <typename C, typename T, typename F, typename KEY>
struct GetRefPtrImpl {
static T const* getRefPtr_(RefCore const& product, KEY const& key) {
T const* item = static_cast<T const*>(product.productPtr());
if (item != nullptr) {
return item;
}
auto prodGetter = product.productGetter();
if (nullptr == prodGetter) {
item = static_cast<T const*>(product.productPtr());
if (item != nullptr) {
//Another thread updated the value since we checked
return item;
}
}
C const* prod = edm::template getProductWithCoreFromRef<C>(product, prodGetter);
/*
typename C::const_iterator it = prod->begin();
std::advance(it, item.key());
T const* p = it.operator->();
*/
F func;
item = func(*prod, key);
product.setProductPtr(item);
return item;
}
};
template <typename C, typename T, typename F>
struct GetRefPtrImpl<C, T, F, unsigned int> {
static T const* getRefPtr_(RefCore const& product, unsigned int key) {
T const* item = static_cast<T const*>(product.productPtr());
if (item != nullptr) {
return item;
}
auto getter = product.productGetter();
if (getter == nullptr) {
auto prod = product.productPtr();
if (prod != nullptr) {
//another thread updated the value since we last checked.
return static_cast<T const*>(prod);
}
}
C const* prod = edm::template tryToGetProductWithCoreFromRef<C>(product, getter);
if (prod != nullptr) {
F func;
item = func(*prod, key);
product.setProductPtr(item);
return item;
}
unsigned int thinnedKey;
std::tie(prod, thinnedKey) = edm::template getThinnedProduct<C>(product, key, getter);
F func;
item = func(*prod, thinnedKey);
product.setProductPtr(item);
return item;
}
};
} // namespace refitem
template <typename C, typename T, typename F, typename KEY>
inline T const* getRefPtr(RefCore const& product, KEY const& iKey) {
return refitem::GetRefPtrImpl<C, T, F, KEY>::getRefPtr_(product, iKey);
}
namespace refitem {
template <typename C, typename KEY>
struct IsThinnedAvailableImpl {
static bool isThinnedAvailable_(RefCore const& product, KEY const& key) { return false; }
};
template <typename C>
struct IsThinnedAvailableImpl<C, unsigned int> {
static bool isThinnedAvailable_(RefCore const& ref, unsigned int key) {
if (ref.productPtr() != nullptr) {
return true;
}
if (ref.isTransient()) {
return false;
}
auto getter = ref.productGetter();
if (getter != nullptr) {
return ref.isThinnedAvailable(key, getter);
}
//another thread may have updated the cache
return nullptr != ref.productPtr();
}
};
} // namespace refitem
template <typename C, typename KEY>
inline bool isThinnedAvailable(RefCore const& product, KEY const& iKey) {
return refitem::IsThinnedAvailableImpl<C, KEY>::isThinnedAvailable_(product, iKey);
}
/// Return a Ref to thinned collection corresponding to an element of the Ref to parent collection
//
// The thinned may point to parent collection, in which case the Ref-to-parent is returned
//
// If thinned does not contain the element of the Ref-to-parent, a Null Ref is returned.
//
// If parent collection is not thinned, or there is no thinning relation between parent and thinned,
// an exception is thrown
template <typename C, typename T, typename F>
Ref<C, T, F> thinnedRefFrom(Ref<C, T, F> const& parent,
RefProd<C> const& thinned,
edm::EDProductGetter const& prodGetter) {
if (parent.id() == thinned.id()) {
return parent;
}
auto thinnedKey = prodGetter.getThinnedKeyFrom(parent.id(), parent.key(), thinned.id());
if (std::holds_alternative<unsigned int>(thinnedKey)) {
return Ref<C, T, F>(thinned, std::get<unsigned int>(thinnedKey));
} else if (std::holds_alternative<detail::GetThinnedKeyFromExceptionFactory>(thinnedKey)) {
auto ex = std::get<detail::GetThinnedKeyFromExceptionFactory>(thinnedKey)();
ex.addContext("Calling edm::thinnedRefFrom()");
throw ex;
}
return Ref<C, T, F>();
}
/// Return a Ref to thinned collection corresponding to an element of the Ref to parent collection
//
// The thinned may point to parent collection, in which case the Ref-to-parent is returned
//
// If thinned does not contain the element of the Ref-to-parent, a Null Ref is returned.
//
// If parent collection is not thinned, or there is no thinning relation between parent and thinned,
// a Null Ref is returned
template <typename C, typename T, typename F>
Ref<C, T, F> tryThinnedRefFrom(Ref<C, T, F> const& parent,
RefProd<C> const& thinned,
edm::EDProductGetter const& prodGetter) {
if (parent.id() == thinned.id()) {
return parent;
}
auto thinnedKey = prodGetter.getThinnedKeyFrom(parent.id(), parent.key(), thinned.id());
if (std::holds_alternative<unsigned int>(thinnedKey)) {
return Ref<C, T, F>(thinned, std::get<unsigned int>(thinnedKey));
}
return Ref<C, T, F>();
}
} // namespace edm
#endif
|