Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-04-06 12:01:20

0001 #include "CommonTools/Utils/interface/parser/MethodInvoker.h"
0002 
0003 #include "CommonTools/Utils/src/ExpressionVar.h"
0004 #include "CommonTools/Utils/interface/parser/MethodSetter.h"
0005 #include "CommonTools/Utils/src/findMethod.h"
0006 #include "CommonTools/Utils/interface/returnType.h"
0007 #include "FWCore/Utilities/interface/EDMException.h"
0008 
0009 #include <algorithm>
0010 //#include <iostream>
0011 using namespace reco::parser;
0012 using namespace std;
0013 
0014 MethodInvoker::MethodInvoker(const edm::FunctionWithDict& method, const vector<AnyMethodArgument>& ints)
0015     : method_(method), member_(), ints_(ints), isFunction_(true) {
0016   setArgs();
0017   if (isFunction_) {
0018     retTypeFinal_ = method_.finalReturnType();
0019   }
0020   //std::cout <<
0021   //   "Booking " <<
0022   //   methodName() <<
0023   //   " from " <<
0024   //   method_.declaringType().name() <<
0025   //   " with " <<
0026   //   args_.size() <<
0027   //   " arguments" <<
0028   //   " (were " <<
0029   //   ints.size() <<
0030   //   ")" <<
0031   //   std::endl;
0032 }
0033 
0034 MethodInvoker::MethodInvoker(const edm::MemberWithDict& member)
0035     : method_(), member_(member), ints_(), isFunction_(false) {
0036   setArgs();
0037   //std::cout <<
0038   //  "Booking " <<
0039   //  methodName() <<
0040   //  " from " <<
0041   //  member_.declaringType().name() <<
0042   //  " with " <<
0043   //  args_.size() <<
0044   //  " arguments" <<
0045   //  " (were " <<
0046   //  ints.size() <<
0047   //  ")" <<
0048   //  std::endl;
0049 }
0050 
0051 MethodInvoker::MethodInvoker(const MethodInvoker& rhs)
0052     : method_(rhs.method_),
0053       member_(rhs.member_),
0054       ints_(rhs.ints_),
0055       isFunction_(rhs.isFunction_),
0056       retTypeFinal_(rhs.retTypeFinal_) {
0057   setArgs();
0058 }
0059 
0060 MethodInvoker& MethodInvoker::operator=(const MethodInvoker& rhs) {
0061   if (this != &rhs) {
0062     method_ = rhs.method_;
0063     member_ = rhs.member_;
0064     ints_ = rhs.ints_;
0065     isFunction_ = rhs.isFunction_;
0066     retTypeFinal_ = rhs.retTypeFinal_;
0067 
0068     setArgs();
0069   }
0070   return *this;
0071 }
0072 
0073 void MethodInvoker::setArgs() {
0074   for (size_t i = 0; i < ints_.size(); ++i) {
0075     args_.push_back(std::visit(AnyMethodArgument2VoidPtr(), ints_[i]));
0076   }
0077 }
0078 
0079 std::string MethodInvoker::methodName() const {
0080   if (isFunction_) {
0081     return method_.name();
0082   }
0083   return member_.name();
0084 }
0085 
0086 std::string MethodInvoker::returnTypeName() const {
0087   if (isFunction_) {
0088     return method_.typeName();
0089   }
0090   return member_.typeOf().qualifiedName();
0091 }
0092 
0093 edm::ObjectWithDict MethodInvoker::invoke(const edm::ObjectWithDict& o, edm::ObjectWithDict& retstore) const {
0094   edm::ObjectWithDict ret = retstore;
0095   edm::TypeWithDict retType;
0096   if (isFunction_) {
0097     //std::cout << "Invoking " << methodName()
0098     //  << " from " << method_.declaringType().qualifiedName()
0099     //  << " on an instance of " << o.dynamicType().qualifiedName()
0100     //  << " at " << o.address()
0101     //  << " with " << args_.size() << " arguments"
0102     //  << std::endl;
0103     method_.invoke(o, &ret, args_);
0104     // this is correct, it takes pointers and refs into account
0105     retType = retTypeFinal_;
0106   } else {
0107     //std::cout << "Invoking " << methodName()
0108     //  << " from " << member_.declaringType().qualifiedName()
0109     //  << " on an instance of " << o.dynamicType().qualifiedName()
0110     //  << " at " << o.address()
0111     //  << " with " << args_.size() << " arguments"
0112     //  << std::endl;
0113     ret = member_.get(o);
0114     retType = member_.typeOf();
0115   }
0116   void* addr = ret.address();
0117   //std::cout << "Stored result of " <<  methodName() << " (type " <<
0118   //  returnTypeName() << ") at " << addr << std::endl;
0119   if (addr == nullptr) {
0120     throw edm::Exception(edm::errors::InvalidReference)
0121         << "method \"" << methodName() << "\" called with " << args_.size() << " arguments returned a null pointer ";
0122   }
0123   //std::cout << "Return type is " << retType.qualifiedName() << std::endl;
0124   if (retType.isPointer() || retType.isReference()) {
0125     // both need void** -> void* conversion
0126     if (retType.isPointer()) {
0127       retType = retType.toType();
0128     } else {
0129       // strip cv & ref flags
0130       // FIXME: This is only true if the propery passed to the constructor
0131       //       overrides the const and reference flags.
0132       retType = retType.stripConstRef();
0133     }
0134     ret = edm::ObjectWithDict(retType, *static_cast<void**>(addr));
0135     //std::cout << "Now type is " << retType.qualifiedName() << std::endl;
0136   }
0137   if (!bool(ret)) {
0138     throw edm::Exception(edm::errors::Configuration)
0139         << "method \"" << methodName() << "\" returned void invoked on object of type \"" << o.typeOf().qualifiedName()
0140         << "\"\n";
0141   }
0142   return ret;
0143 }
0144 
0145 LazyInvoker::LazyInvoker(const std::string& name, const std::vector<AnyMethodArgument>& args)
0146     : name_(name), argsBeforeFixups_(args) {}
0147 
0148 LazyInvoker::~LazyInvoker() {}
0149 
0150 const SingleInvoker& LazyInvoker::invoker(const edm::TypeWithDict& type) const {
0151   //std::cout << "LazyInvoker for " << name_ << " called on type " <<
0152   //  type.qualifiedName() << std::endl;
0153   const edm::TypeID thetype(type.typeInfo());
0154   auto found = invokers_.find(thetype);
0155   if (found != invokers_.cend()) {
0156     return *(found->second);
0157   }
0158   auto to_add = std::make_shared<SingleInvoker>(type, name_, argsBeforeFixups_);
0159   auto emplace_result = invokers_.insert(std::make_pair(thetype, to_add));
0160   return *(emplace_result.first->second);
0161 }
0162 
0163 edm::ObjectWithDict LazyInvoker::invoke(const edm::ObjectWithDict& o, std::vector<StorageManager>& v) const {
0164   pair<edm::ObjectWithDict, bool> ret(o, false);
0165   do {
0166     edm::TypeWithDict type = ret.first.typeOf();
0167     if (type.isClass()) {
0168       type = ret.first.dynamicType();
0169     }
0170     ret = invoker(type).invoke(edm::ObjectWithDict(type, ret.first.address()), v);
0171   } while (ret.second == false);
0172   return ret.first;
0173 }
0174 
0175 double LazyInvoker::invokeLast(const edm::ObjectWithDict& o, std::vector<StorageManager>& v) const {
0176   pair<edm::ObjectWithDict, bool> ret(o, false);
0177   const SingleInvoker* i = nullptr;
0178   do {
0179     edm::TypeWithDict type = ret.first.typeOf();
0180     if (type.isClass()) {
0181       type = ret.first.dynamicType();
0182     }
0183     i = &invoker(type);
0184     ret = i->invoke(edm::ObjectWithDict(type, ret.first.address()), v);
0185   } while (ret.second == false);
0186   return i->retToDouble(ret.first);
0187 }
0188 
0189 SingleInvoker::SingleInvoker(const edm::TypeWithDict& type,
0190                              const std::string& name,
0191                              const std::vector<AnyMethodArgument>& args) {
0192   TypeStack typeStack(1, type);
0193   LazyMethodStack dummy;
0194   MethodArgumentStack dummy2;
0195   MethodSetter setter(invokers_, dummy, typeStack, dummy2, false);
0196   isRefGet_ = !setter.push(name, args, "LazyInvoker dynamic resolution", false);
0197   //std::cerr  << "SingleInvoker on type " <<  type.qualifiedName() <<
0198   //  ", name " << name << (isRefGet_ ? " is just a ref.get " : " is real") <<
0199   //  std::endl;
0200   returnStorage(createStorage(storageNeedsDestructor_));
0201   // typeStack[0] = type of self
0202   // typeStack[1] = type of ret
0203   retType_ = reco::typeCode(typeStack[1]);
0204 }
0205 
0206 SingleInvoker::~SingleInvoker() {
0207   edm::ObjectWithDict stored;
0208   while (storage_.try_pop(stored)) {
0209     //std::cout <<"deleting "<<stored.address()<<" from "<<this<<std::endl;
0210     ExpressionVar::delStorage(stored);
0211   }
0212 }
0213 
0214 edm::ObjectWithDict SingleInvoker::createStorage(bool& needsDestructor) const {
0215   if (invokers_.front().isFunction()) {
0216     edm::TypeWithDict retType = invokers_.front().method().finalReturnType();
0217     edm::ObjectWithDict stored;
0218     needsDestructor = ExpressionVar::makeStorage(stored, retType);
0219     return stored;
0220   }
0221   needsDestructor = false;
0222   return edm::ObjectWithDict();
0223 }
0224 
0225 edm::ObjectWithDict SingleInvoker::borrowStorage() const {
0226   edm::ObjectWithDict o;
0227   if (storage_.try_pop(o)) {
0228     //std::cout <<"borrowed "<<o.address()<<" from "<<this<<std::endl;
0229     return o;
0230   }
0231   bool dummy;
0232   o = createStorage(dummy);
0233   //std::cout <<"borrowed new "<<o.address()<<std::endl;
0234   return o;
0235 }
0236 
0237 void SingleInvoker::returnStorage(edm::ObjectWithDict&& o) const {
0238   //std::cout <<"returned "<<o.address()<<" to "<<this<<std::endl;
0239   storage_.push(std::move(o));
0240 }
0241 
0242 pair<edm::ObjectWithDict, bool> SingleInvoker::invoke(const edm::ObjectWithDict& o,
0243                                                       std::vector<StorageManager>& v) const {
0244   // std::cerr << "[SingleInvoker::invoke] member " <<
0245   //   invokers_.front().method().qualifiedName() <<
0246   //   " of type " <<
0247   //   o.typeOf().qualifiedName() <<
0248   //   (!isRefGet_ ? " is one shot" : " needs another round") <<
0249   //   std::endl;
0250   auto storage = borrowStorage();
0251   pair<edm::ObjectWithDict, bool> ret(invokers_.front().invoke(o, storage), !isRefGet_);
0252   v.emplace_back(storage, this, storageNeedsDestructor_);
0253   return ret;
0254 }
0255 
0256 double SingleInvoker::retToDouble(const edm::ObjectWithDict& o) const {
0257   if (!ExpressionVar::isValidReturnType(retType_)) {
0258     throwFailedConversion(o);
0259   }
0260   return ExpressionVar::objToDouble(o, retType_);
0261 }
0262 
0263 void SingleInvoker::throwFailedConversion(const edm::ObjectWithDict& o) const {
0264   throw edm::Exception(edm::errors::Configuration)
0265       << "member \"" << invokers_.back().methodName() << "\" return type is \"" << invokers_.back().returnTypeName()
0266       << "\" retured a \"" << o.typeOf().qualifiedName() << "\" which is not convertible to double.";
0267 }
0268 
0269 StorageManager::~StorageManager() {
0270   if (needsDestructor_) {
0271     object_.destruct(false);
0272   }
0273   if (invoker_) {
0274     invoker_->returnStorage(std::move(object_));
0275   }
0276 }