|
| 1 | +#include "CommonTools/Utils/interface/parser/MethodChain.h" |
| 2 | +#include "CommonTools/Utils/interface/parser/MethodInvoker.h" |
| 3 | + |
| 4 | +#include "FWCore/Reflection/interface/ObjectWithDict.h" |
| 5 | +#include "FWCore/Reflection/interface/FunctionWithDict.h" |
| 6 | +#include "FWCore/Reflection/interface/MemberWithDict.h" |
| 7 | +#include "FWCore/Reflection/interface/TypeWithDict.h" |
| 8 | + |
| 9 | +#include <cassert> |
| 10 | +#include <map> |
| 11 | + |
| 12 | +using namespace reco::parser; |
| 13 | +using namespace std; |
| 14 | + |
| 15 | +MethodChain::Objects MethodChain::initObjects_() const { |
| 16 | + Objects objects(methods_.size(), {edm::ObjectWithDict(), false}); |
| 17 | + assert(objects.size() == methods_.size()); |
| 18 | + auto IO = objects.begin(); |
| 19 | + for (auto const& method : methods_) { |
| 20 | + if (method.isFunction()) { |
| 21 | + edm::TypeWithDict retType = method.method().finalReturnType(); |
| 22 | + IO->second = makeStorage(IO->first, retType); |
| 23 | + } else { |
| 24 | + *IO = {edm::ObjectWithDict(), false}; |
| 25 | + } |
| 26 | + ++IO; |
| 27 | + } |
| 28 | + return objects; |
| 29 | +} |
| 30 | + |
| 31 | +MethodChain::MethodChain(const vector<MethodInvoker>& methods) |
| 32 | + : methods_(methods) { |
| 33 | + returnObjects(initObjects_()); |
| 34 | +} |
| 35 | + |
| 36 | +MethodChain::MethodChain(const MethodChain& rhs) : methods_(rhs.methods_) { |
| 37 | + returnObjects(initObjects_()); |
| 38 | +} |
| 39 | + |
| 40 | +MethodChain::Objects MethodChain::borrowObjects() const { |
| 41 | + Objects objects; |
| 42 | + if (objectsCache_.try_pop(objects)) { |
| 43 | + return objects; |
| 44 | + } |
| 45 | + return initObjects_(); |
| 46 | +} |
| 47 | + |
| 48 | +void MethodChain::returnObjects(Objects&& iOb) const { objectsCache_.push(std::move(iOb)); } |
| 49 | + |
| 50 | +MethodChain::~MethodChain() { |
| 51 | + Objects objects; |
| 52 | + while (objectsCache_.try_pop(objects)) { |
| 53 | + for (auto& o : objects) { |
| 54 | + delStorage(o.first); |
| 55 | + } |
| 56 | + } |
| 57 | +} |
| 58 | + |
| 59 | +void MethodChain::delStorage(edm::ObjectWithDict& obj) { |
| 60 | + if (!obj.address()) { |
| 61 | + return; |
| 62 | + } |
| 63 | + if (obj.typeOf().isPointer() || obj.typeOf().isReference()) { |
| 64 | + // just delete a void*, as that's what it was |
| 65 | + void** p = static_cast<void**>(obj.address()); |
| 66 | + delete p; |
| 67 | + } else { |
| 68 | + //std::cout << "Calling Destruct on a " << |
| 69 | + // obj.typeOf().qualifiedName() << std::endl; |
| 70 | + obj.typeOf().deallocate(obj.address()); |
| 71 | + } |
| 72 | +} |
| 73 | + |
| 74 | +bool MethodChain::makeStorage(edm::ObjectWithDict& obj, const edm::TypeWithDict& retType) { |
| 75 | + static const edm::TypeWithDict tVoid(edm::TypeWithDict::byName("void")); |
| 76 | + bool ret = false; |
| 77 | + if (retType == tVoid) { |
| 78 | + obj = edm::ObjectWithDict::byType(tVoid); |
| 79 | + } else if (retType.isPointer() || retType.isReference()) { |
| 80 | + // in this case, I have to allocate a void*, not an object! |
| 81 | + obj = edm::ObjectWithDict(retType, new void*); |
| 82 | + } else { |
| 83 | + obj = edm::ObjectWithDict(retType, retType.allocate()); |
| 84 | + ret = retType.isClass(); |
| 85 | + //std::cout << "MethodChain: reserved memory at " << obj.address() << |
| 86 | + // " for a " << retType.qualifiedName() << " returned by " << |
| 87 | + // member.name() << std::endl; |
| 88 | + } |
| 89 | + return ret; |
| 90 | +} |
| 91 | + |
| 92 | +edm::ObjectWithDict MethodChain::value(const edm::ObjectWithDict& obj) const { |
| 93 | + edm::ObjectWithDict val(obj); |
| 94 | + auto objects = borrowObjects(); |
| 95 | + auto IO = objects.begin(); |
| 96 | + for (auto& m : methods_) { |
| 97 | + val = m.invoke(val, IO->first); |
| 98 | + ++IO; |
| 99 | + } |
| 100 | + for (auto RI = objects.rbegin(), RE = objects.rend(); RI != RE; ++RI) { |
| 101 | + if (RI->second) { |
| 102 | + RI->first.destruct(false); |
| 103 | + } |
| 104 | + } |
| 105 | + returnObjects(std::move(objects)); |
| 106 | + return val; |
| 107 | +} |
| 108 | + |
| 109 | +LazyMethodChain::LazyMethodChain(const std::vector<LazyInvoker>& methods) : methods_(methods) {} |
| 110 | + |
| 111 | +LazyMethodChain::~LazyMethodChain() {} |
| 112 | + |
| 113 | +edm::ObjectWithDict LazyMethodChain::value(const edm::ObjectWithDict& o) const { |
| 114 | + edm::ObjectWithDict val = o; |
| 115 | + std::vector<StorageManager> storage; |
| 116 | + storage.reserve(methods_.size()); |
| 117 | + |
| 118 | + std::vector<LazyInvoker>::const_iterator I = methods_.begin(); |
| 119 | + std::vector<LazyInvoker>::const_iterator E = methods_.end(); |
| 120 | + for (; I < E; ++I) { |
| 121 | + val = I->invoke(val, storage); |
| 122 | + } |
| 123 | + while (not storage.empty()) { |
| 124 | + storage.pop_back(); |
| 125 | + } |
| 126 | + return val; |
| 127 | +} |
0 commit comments