File indexing completed on 2025-01-09 23:33:16
0001 #include "CommonTools/Utils/interface/parser/MethodChain.h"
0002 #include "CommonTools/Utils/interface/parser/MethodInvoker.h"
0003
0004 #include "FWCore/Reflection/interface/ObjectWithDict.h"
0005 #include "FWCore/Reflection/interface/FunctionWithDict.h"
0006 #include "FWCore/Reflection/interface/MemberWithDict.h"
0007 #include "FWCore/Reflection/interface/TypeWithDict.h"
0008
0009 #include <cassert>
0010 #include <map>
0011
0012 using namespace reco::parser;
0013 using namespace std;
0014
0015 MethodChain::Objects MethodChain::initObjects_() const {
0016 Objects objects(methods_.size(), {edm::ObjectWithDict(), false});
0017 assert(objects.size() == methods_.size());
0018 auto IO = objects.begin();
0019 for (auto const& method : methods_) {
0020 if (method.isFunction()) {
0021 edm::TypeWithDict retType = method.method().finalReturnType();
0022 IO->second = makeStorage(IO->first, retType);
0023 } else {
0024 *IO = {edm::ObjectWithDict(), false};
0025 }
0026 ++IO;
0027 }
0028 return objects;
0029 }
0030
0031 MethodChain::MethodChain(const vector<MethodInvoker>& methods) : methods_(methods) { returnObjects(initObjects_()); }
0032
0033 MethodChain::MethodChain(const MethodChain& rhs) : methods_(rhs.methods_) { returnObjects(initObjects_()); }
0034
0035 MethodChain::Objects MethodChain::borrowObjects() const {
0036 Objects objects;
0037 if (objectsCache_.try_pop(objects)) {
0038 return objects;
0039 }
0040 return initObjects_();
0041 }
0042
0043 void MethodChain::returnObjects(Objects&& iOb) const { objectsCache_.push(std::move(iOb)); }
0044
0045 MethodChain::~MethodChain() {
0046 Objects objects;
0047 while (objectsCache_.try_pop(objects)) {
0048 for (auto& o : objects) {
0049 delStorage(o.first);
0050 }
0051 }
0052 }
0053
0054 void MethodChain::delStorage(edm::ObjectWithDict& obj) {
0055 if (!obj.address()) {
0056 return;
0057 }
0058 if (obj.typeOf().isPointer() || obj.typeOf().isReference()) {
0059
0060 void** p = static_cast<void**>(obj.address());
0061 delete p;
0062 } else {
0063
0064
0065 obj.typeOf().deallocate(obj.address());
0066 }
0067 }
0068
0069 bool MethodChain::makeStorage(edm::ObjectWithDict& obj, const edm::TypeWithDict& retType) {
0070 static const edm::TypeWithDict tVoid(edm::TypeWithDict::byName("void"));
0071 bool ret = false;
0072 if (retType == tVoid) {
0073 obj = edm::ObjectWithDict::byType(tVoid);
0074 } else if (retType.isPointer() || retType.isReference()) {
0075
0076 obj = edm::ObjectWithDict(retType, new void*);
0077 } else {
0078 obj = edm::ObjectWithDict(retType, retType.allocate());
0079 ret = retType.isClass();
0080
0081
0082
0083 }
0084 return ret;
0085 }
0086
0087 edm::ObjectWithDict MethodChain::value(const edm::ObjectWithDict& obj) const {
0088 edm::ObjectWithDict val(obj);
0089 auto objects = borrowObjects();
0090 auto IO = objects.begin();
0091 for (auto& m : methods_) {
0092 val = m.invoke(val, IO->first);
0093 ++IO;
0094 }
0095 for (auto RI = objects.rbegin(), RE = objects.rend(); RI != RE; ++RI) {
0096 if (RI->second) {
0097 RI->first.destruct(false);
0098 }
0099 }
0100 returnObjects(std::move(objects));
0101 return val;
0102 }
0103
0104 LazyMethodChain::LazyMethodChain(const std::vector<LazyInvoker>& methods) : methods_(methods) {}
0105
0106 LazyMethodChain::~LazyMethodChain() {}
0107
0108 edm::ObjectWithDict LazyMethodChain::value(const edm::ObjectWithDict& o) const {
0109 edm::ObjectWithDict val = o;
0110 std::vector<StorageManager> storage;
0111 storage.reserve(methods_.size());
0112
0113 std::vector<LazyInvoker>::const_iterator I = methods_.begin();
0114 std::vector<LazyInvoker>::const_iterator E = methods_.end();
0115 for (; I < E; ++I) {
0116 val = I->invoke(val, storage);
0117 }
0118 while (not storage.empty()) {
0119 storage.pop_back();
0120 }
0121 return val;
0122 }