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
|
#ifndef DataFormats_Common_RefCore_h
#define DataFormats_Common_RefCore_h
/*----------------------------------------------------------------------
RefCore: The component of edm::Ref containing the product ID and product getter.
----------------------------------------------------------------------*/
#include "DataFormats/Provenance/interface/ProductID.h"
#include "DataFormats/Common/interface/refcore_implementation.h"
#include <algorithm>
#include <typeinfo>
#include <atomic>
namespace edm {
class RefCoreWithIndex;
class EDProductGetter;
class WrapperBase;
class RefCore {
//RefCoreWithIndex is a specialization of RefCore done for performance
// Since we need to freely convert one to the other the friendship is used
friend class RefCoreWithIndex;
public:
RefCore() : cachePtr_(nullptr), processIndex_(0), productIndex_(0) {}
RefCore(ProductID const& theId, void const* prodPtr, EDProductGetter const* prodGetter, bool transient);
RefCore(RefCore const&);
RefCore& operator=(RefCore const&);
RefCore(RefCore&& iOther) noexcept : processIndex_(iOther.processIndex_), productIndex_(iOther.productIndex_) {
cachePtr_.store(iOther.cachePtr_.load(std::memory_order_relaxed), std::memory_order_relaxed);
}
RefCore& operator=(RefCore&& iOther) noexcept {
cachePtr_.store(iOther.cachePtr_.load(std::memory_order_relaxed), std::memory_order_relaxed);
processIndex_ = iOther.processIndex_;
productIndex_ = iOther.productIndex_;
return *this;
}
~RefCore() noexcept {}
ProductID id() const { ID_IMPL; }
/**If productPtr is not 0 then productGetter will be 0 since only one is available at a time */
void const* productPtr() const { PRODUCTPTR_IMPL; }
/**This function is 'const' even though it changes an internal value becuase it is meant to be
used as a way to store in a thread-safe way a cache of a value. This allows classes which use
the RefCore to not have to declare it 'mutable'
*/
void setProductPtr(void const* prodPtr) const { setCacheIsProductPtr(prodPtr); }
/**This function is 'const' even though it changes an internal value becuase it is meant to be
used as a way to store in a thread-safe way a cache of a value. This allows classes which use
the RefCore to not have to declare it 'mutable'
*/
bool tryToSetProductPtrForFirstTime(void const* prodPtr) const {
return refcoreimpl::tryToSetCacheItemForFirstTime(cachePtr_, prodPtr);
}
// Checks for null
bool isNull() const { return !isNonnull(); }
// Checks for non-null
bool isNonnull() const { ISNONNULL_IMPL; }
// Checks for null
bool operator!() const { return isNull(); }
// Checks if collection is in memory or available
// in the Event. No type checking is done.
bool isAvailable() const;
EDProductGetter const* productGetter() const { PRODUCTGETTER_IMPL; }
void setProductGetter(EDProductGetter const* prodGetter) const;
WrapperBase const* getProductPtr(std::type_info const& type, EDProductGetter const* prodGetter) const;
WrapperBase const* tryToGetProductPtr(std::type_info const& type, EDProductGetter const* prodGetter) const;
// argument 'key' is the key to parent, key to thinned is returned
std::tuple<WrapperBase const*, unsigned int> getThinnedProductPtr(std::type_info const& type,
unsigned int key,
EDProductGetter const* prodGetter) const;
// argument 'key' is the key to parent
bool isThinnedAvailable(unsigned int key, EDProductGetter const* prodGetter) const;
void productNotFoundException(std::type_info const& type) const;
void wrongTypeException(std::type_info const& expectedType, std::type_info const& actualType) const;
void nullPointerForTransientException(std::type_info const& type) const;
void swap(RefCore&) noexcept;
bool isTransient() const { ISTRANSIENT_IMPL; }
int isTransientInt() const { return isTransient() ? 1 : 0; }
void pushBackItem(RefCore const& productToBeInserted, bool checkPointer);
void pushBackRefItem(RefCore const& productToBeInserted);
private:
RefCore(void const* iCache, ProcessIndex iProcessIndex, ProductIndex iProductIndex)
: cachePtr_(iCache), processIndex_(iProcessIndex), productIndex_(iProductIndex) {}
void setId(ProductID const& iId);
void setTransient() { SETTRANSIENT_IMPL; }
void setCacheIsProductPtr(const void* iItem) const { SETCACHEISPRODUCTPTR_IMPL(iItem); }
void setCacheIsProductGetter(EDProductGetter const* iGetter) const { SETCACHEISPRODUCTGETTER_IMPL(iGetter); }
bool cachePtrIsInvalid() const {
return 0 == (reinterpret_cast<std::uintptr_t>(cachePtr_.load()) & refcoreimpl::kCacheIsProductPtrMask);
}
//The low bit of the address is used to determine if the cachePtr_
// is storing the productPtr or the EDProductGetter. The bit is set if
// the address refers to the EDProductGetter.
mutable std::atomic<void const*> cachePtr_; // transient
//The following is what is stored in a ProductID
// the high bit of processIndex is used to store info on
// if this is transient.
//If the type or order of the member data is changes you MUST also update
// the custom streamer in RefCoreStreamer.cc and RefCoreWithIndex
ProcessIndex processIndex_;
ProductIndex productIndex_;
};
inline bool operator==(RefCore const& lhs, RefCore const& rhs) {
return lhs.isTransient() == rhs.isTransient() &&
(lhs.isTransient() ? lhs.productPtr() == rhs.productPtr() : lhs.id() == rhs.id());
}
inline bool operator!=(RefCore const& lhs, RefCore const& rhs) { return !(lhs == rhs); }
inline bool operator<(RefCore const& lhs, RefCore const& rhs) {
return lhs.isTransient() ? (rhs.isTransient() ? lhs.productPtr() < rhs.productPtr() : false)
: (rhs.isTransient() ? true : lhs.id() < rhs.id());
}
inline void RefCore::swap(RefCore& other) noexcept {
std::swap(processIndex_, other.processIndex_);
std::swap(productIndex_, other.productIndex_);
other.cachePtr_.store(cachePtr_.exchange(other.cachePtr_.load()));
}
inline void swap(edm::RefCore& lhs, edm::RefCore& rhs) { lhs.swap(rhs); }
} // namespace edm
#endif
|