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
|
#ifndef CommonTools_Utils_MethodInvoker_h
#define CommonTools_Utils_MethodInvoker_h
#include "CommonTools/Utils/interface/parser/AnyMethodArgument.h"
#include "CommonTools/Utils/interface/TypeCode.h"
#include "FWCore/Reflection/interface/FunctionWithDict.h"
#include "FWCore/Reflection/interface/MemberWithDict.h"
#include "FWCore/Reflection/interface/ObjectWithDict.h"
#include "FWCore/Utilities/interface/TypeID.h"
#include <map>
#include <vector>
#include "oneapi/tbb/concurrent_unordered_map.h"
#include "oneapi/tbb/concurrent_queue.h"
namespace edm {
struct TypeIDHasher {
size_t operator()(TypeID const& tid) const { return std::hash<std::string>{}(std::string(tid.name())); }
};
} // namespace edm
namespace reco {
namespace parser {
class MethodInvoker {
private: // Private Data Members
edm::FunctionWithDict method_;
edm::MemberWithDict member_;
std::vector<AnyMethodArgument> ints_; // already fixed to the correct type
std::vector<void*> args_;
bool isFunction_;
edm::TypeWithDict retTypeFinal_;
private: // Private Function Members
void setArgs();
public: // Public Function Members
explicit MethodInvoker(const edm::FunctionWithDict& method,
const std::vector<AnyMethodArgument>& ints = std::vector<AnyMethodArgument>());
explicit MethodInvoker(const edm::MemberWithDict&);
MethodInvoker(const MethodInvoker&);
MethodInvoker& operator=(const MethodInvoker&);
edm::FunctionWithDict const method() const { return method_; }
edm::MemberWithDict const member() const { return member_; }
bool isFunction() const { return isFunction_; }
std::string methodName() const;
std::string returnTypeName() const;
/// Invokes the method, putting the result in retval.
/// Returns the Object that points to the result value,
/// after removing any "*" and "&"
/// Caller code is responsible for allocating retstore
/// before calling 'invoke', and of deallocating it afterwards
edm::ObjectWithDict invoke(const edm::ObjectWithDict& obj, edm::ObjectWithDict& retstore) const;
};
struct SingleInvoker;
//Handles temporary object storage
struct StorageManager {
private:
edm::ObjectWithDict object_;
SingleInvoker const* invoker_;
bool needsDestructor_;
public:
StorageManager(edm::ObjectWithDict const& iObj, SingleInvoker const* iInvoker, bool iNeedsDestructor_)
: object_(iObj), invoker_(iInvoker), needsDestructor_(iNeedsDestructor_) {}
StorageManager(const StorageManager&) = delete;
StorageManager(StorageManager&& iOther)
: object_(iOther.object_), invoker_(iOther.invoker_), needsDestructor_(iOther.needsDestructor_) {
iOther.needsDestructor_ = false;
iOther.invoker_ = nullptr;
}
StorageManager& operator=(const StorageManager&) = delete;
StorageManager& operator=(StorageManager&&) = delete;
~StorageManager();
};
/// A bigger brother of the MethodInvoker:
/// - it owns also the object in which to store the result
/// - it handles by itself the popping out of Refs and Ptrs
/// in this way, it can map 1-1 to a name and set of args
struct SingleInvoker {
private: // Private Data Members
method::TypeCode retType_;
std::vector<MethodInvoker> invokers_;
mutable oneapi::tbb::concurrent_queue<edm::ObjectWithDict> storage_;
bool storageNeedsDestructor_;
/// true if this invoker just pops out a ref and returns (ref.get(), false)
bool isRefGet_;
edm::ObjectWithDict borrowStorage() const;
edm::ObjectWithDict createStorage(bool& needsDestructor) const;
public:
SingleInvoker(const SingleInvoker&) = delete;
SingleInvoker& operator=(const SingleInvoker&) = delete;
SingleInvoker(const edm::TypeWithDict&, const std::string& name, const std::vector<AnyMethodArgument>& args);
~SingleInvoker();
/// If the member is found in object o, evaluate and
/// return (value,true)
/// If the member is not found but o is a Ref/RefToBase/Ptr,
/// (return o.get(), false)
/// the actual edm::ObjectWithDict where the result is stored
/// will be pushed in vector so that, if needed, its destructor
/// can be called
std::pair<edm::ObjectWithDict, bool> invoke(const edm::ObjectWithDict& o, std::vector<StorageManager>& v) const;
/// convert the output of invoke to a double, if possible
double retToDouble(const edm::ObjectWithDict&) const;
void throwFailedConversion(const edm::ObjectWithDict&) const;
void returnStorage(edm::ObjectWithDict&&) const;
};
/// Keeps different SingleInvokers for each dynamic type of the objects passed to invoke()
struct LazyInvoker {
typedef std::shared_ptr<SingleInvoker> SingleInvokerPtr;
typedef tbb::concurrent_unordered_map<edm::TypeID, SingleInvokerPtr, edm::TypeIDHasher> InvokerMap;
private: // Private Data Members
std::string name_;
std::vector<AnyMethodArgument> argsBeforeFixups_;
// the shared ptr is only to make the code exception safe
// otherwise I think it could leak if the constructor of
// SingleInvoker throws an exception (which can happen)
mutable InvokerMap invokers_;
private: // Private Function Members
const SingleInvoker& invoker(const edm::TypeWithDict&) const;
public: // Public Function Members
explicit LazyInvoker(const std::string& name, const std::vector<AnyMethodArgument>& args);
~LazyInvoker();
/// invoke method, returns object that points to result
/// (after stripping '*' and '&')
/// the object is still owned by the LazyInvoker
/// the actual edm::ObjectWithDict where the result is
/// stored will be pushed in vector
/// so that, if needed, its destructor can be called
edm::ObjectWithDict invoke(const edm::ObjectWithDict& o, std::vector<StorageManager>& v) const;
/// invoke and coerce result to double
double invokeLast(const edm::ObjectWithDict& o, std::vector<StorageManager>& v) const;
};
} // namespace parser
} // namespace reco
#endif // CommonTools_Utils_MethodInvoker_h
|