CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_6_1_2_SLHC4_patch1/src/CommonTools/Utils/src/MethodInvoker.cc

Go to the documentation of this file.
00001 #include "CommonTools/Utils/src/MethodInvoker.h"
00002 #include "CommonTools/Utils/src/findMethod.h"
00003 #include "CommonTools/Utils/src/returnType.h"
00004 #include "FWCore/Utilities/interface/EDMException.h"
00005 #include "CommonTools/Utils/src/MethodSetter.h"
00006 #include "CommonTools/Utils/src/ExpressionVar.h"
00007 
00008 #include <algorithm>
00009 using namespace reco::parser;
00010 using namespace std;
00011 
00012 MethodInvoker::MethodInvoker(const edm::FunctionWithDict & method, const vector<AnyMethodArgument> & ints) :
00013   method_(method), member_(), ints_(ints), isFunction_(true)
00014 { 
00015   setArgs();
00016   /*std::cout << "Booking " << methodName() 
00017             << " from " << method_.declaringType().name() 
00018             << " with " << args_.size() << " arguments"
00019             << " (were " << ints.size() << ")"
00020             << std::endl;*/
00021 }
00022 
00023 MethodInvoker::MethodInvoker(const edm::MemberWithDict & member) :
00024   method_(), member_(member), ints_(), isFunction_(false)
00025 { 
00026   setArgs();
00027   /*std::cout << "Booking " << methodName() 
00028             << " from " << member_.declaringType().name() 
00029             << " with " << args_.size() << " arguments"
00030             << " (were " << ints.size() << ")"
00031             << std::endl;*/
00032 }
00033 
00034 MethodInvoker::MethodInvoker(const MethodInvoker & other) :
00035   method_(other.method_), member_(other.member_), ints_(other.ints_), isFunction_(other.isFunction_) {
00036   setArgs();
00037 }
00038 
00039 MethodInvoker & MethodInvoker::operator=(const MethodInvoker & other) {
00040   method_ = other.method_;
00041   member_ = other.member_;
00042   ints_ = other.ints_;
00043   isFunction_ = other.isFunction_;
00044   setArgs();
00045   return *this;
00046 }
00047 
00048 void MethodInvoker::setArgs() {
00049   for(size_t i = 0; i < ints_.size(); ++i) {
00050       args_.push_back( boost::apply_visitor( AnyMethodArgument2VoidPtr(), ints_[i] ) );
00051   }
00052 }
00053 
00054 std::string
00055 MethodInvoker::methodName() const {
00056   if(isFunction_) {
00057      return method_.name();
00058   }
00059   return member_.name();
00060 }
00061 
00062 std::string
00063 MethodInvoker::returnTypeName() const {
00064   if(isFunction_) {
00065      return method_.typeOf().name(edm::TypeNameHandling::Qualified);
00066   }
00067   return member_.typeOf().name(edm::TypeNameHandling::Qualified);
00068 }
00069 
00070 edm::ObjectWithDict
00071 MethodInvoker::invoke(const edm::ObjectWithDict & o, edm::ObjectWithDict &retstore) const {
00072   edm::ObjectWithDict ret = retstore;
00073   edm::TypeWithDict retType;
00074   if(isFunction_) {
00075      /*std::cout << "Invoking " << methodName() 
00076             << " from " << method_.declaringType().name(edm::TypeNameHandling::Qualified) 
00077             << " on an instance of " << o.dynamicType().name(edm::TypeNameHandling::Qualified) 
00078             << " at " << o.address()
00079             << " with " << args_.size() << " arguments"
00080             << std::endl; */
00081      method_.invoke(o, &ret, args_);
00082      retType = method_.returnType(); // this is correct, it takes pointers and refs into account
00083   } else {
00084      /*std::cout << "Invoking " << methodName() 
00085             << " from " << member_.declaringType().name(edm::TypeNameHandling::Qualified) 
00086             << " on an instance of " << o.dynamicType().name(edm::TypeNameHandling::Qualified) 
00087             << " at " << o.address()
00088             << " with " << args_.size() << " arguments"
00089             << std::endl; */
00090      ret = member_.get(o);
00091      retType = member_.typeOf();
00092   }
00093   void * addr = ret.address(); 
00094   //std::cout << "Stored result of " <<  methodName() << " (type " << returnTypeName() << ") at " << addr << std::endl;
00095   if(addr==0) {
00096     throw edm::Exception(edm::errors::InvalidReference)
00097       << "method \"" << methodName() << "\" called with " << args_.size() 
00098       << " arguments returned a null pointer ";   
00099   }
00100   //std::cout << "Return type is " << retType.name(edm::TypeNameHandling::Qualified) << std::endl;
00101    
00102   if(retType.isPointer() || retType.isReference()) { // both need (void **)->(void *) conversion
00103       if (retType.isPointer()) {
00104         retType = retType.toType(); // for Pointers, I get the real type this way
00105       } else {
00106         retType = edm::TypeWithDict(retType, edm::TypeModifiers::NoMod); // strip cv & ref flags
00107       }
00108       while (retType.isTypedef()) retType = retType.toType();
00109       ret = edm::ObjectWithDict(retType, *static_cast<void **>(addr));
00110       //std::cout << "Now type is " << retType.name(edm::TypeNameHandling::Qualified) << std::endl;
00111   }
00112   if(!ret) {
00113      throw edm::Exception(edm::errors::Configuration)
00114       << "method \"" << methodName()
00115       << "\" returned void invoked on object of type \"" 
00116       << o.typeOf().name(edm::TypeNameHandling::Qualified) << "\"\n";
00117   }
00118   return ret;
00119 }
00120 
00121 LazyInvoker::LazyInvoker(const std::string &name, const std::vector<AnyMethodArgument> & args) :
00122     name_(name),
00123     argsBeforeFixups_(args)
00124 {
00125 }
00126 
00127 LazyInvoker::~LazyInvoker() 
00128 {
00129 }
00130 
00131 const SingleInvoker &
00132 LazyInvoker::invoker(const edm::TypeWithDict & type) const 
00133 {
00134     //std::cout << "LazyInvoker for " << name_ << " called on type " << type.name(edm::TypeNameHandling::Qualified) << std::endl;
00135     SingleInvokerPtr & invoker = invokers_[type.id()];
00136     if (!invoker) {
00137         //std::cout << "  Making new invoker for " << name_ << " on type " << type.name(edm::TypeNameHandling::Qualified) << std::endl;
00138         invoker.reset(new SingleInvoker(type, name_, argsBeforeFixups_));
00139     } 
00140     return * invoker;
00141 }
00142 
00143 edm::ObjectWithDict
00144 LazyInvoker::invoke(const edm::ObjectWithDict & o, std::vector<edm::ObjectWithDict> &v) const 
00145 {
00146     pair<edm::ObjectWithDict, bool> ret(o,false);
00147     do {    
00148         edm::TypeWithDict type = ret.first.typeOf();
00149         if (type.isClass()) type = ret.first.dynamicType();
00150         ret = invoker(type).invoke(edm::ObjectWithDict(type, ret.first.address()), v);
00151     } while (ret.second == false);
00152     return ret.first; 
00153 }
00154 
00155 double
00156 LazyInvoker::invokeLast(const edm::ObjectWithDict & o, std::vector<edm::ObjectWithDict> &v) const 
00157 {
00158     pair<edm::ObjectWithDict, bool> ret(o,false);
00159     const SingleInvoker *i = 0;
00160     do {    
00161         edm::TypeWithDict type = ret.first.typeOf();
00162         if (type.isClass()) type = ret.first.dynamicType();
00163         i = & invoker(type);
00164         ret = i->invoke(edm::ObjectWithDict(type, ret.first.address()), v);
00165     } while (ret.second == false);
00166     return i->retToDouble(ret.first);
00167 }
00168 
00169 SingleInvoker::SingleInvoker(const edm::TypeWithDict &type,
00170         const std::string &name,
00171         const std::vector<AnyMethodArgument> &args) 
00172 {
00173     TypeStack typeStack(1, type);
00174     LazyMethodStack dummy;
00175     MethodArgumentStack dummy2;
00176     MethodSetter setter(invokers_, dummy, typeStack, dummy2, false);
00177     isRefGet_ = !setter.push(name, args, "LazyInvoker dynamic resolution", false);
00178     //std::cerr  << "SingleInvoker on type " <<  type.qualifiedName() << ", name " << name << (isRefGet_ ? " is just a ref.get " : " is real") << std::endl;
00179     //remove any typedefs if any. If we do not do this it appears that we get a memory leak
00180     // because typedefs do not have 'destructors'
00181     if(invokers_.front().isFunction()) {
00182        edm::TypeWithDict retType = invokers_.front().method().returnType().finalType();
00183        storageNeedsDestructor_ = ExpressionVar::makeStorage(storage_, retType);
00184     } else {
00185        storage_ = edm::ObjectWithDict();
00186        storageNeedsDestructor_ = false;
00187     }
00188     retType_ = reco::typeCode(typeStack[1]); // typeStack[0] = type of self, typeStack[1] = type of ret
00189 }
00190 
00191 SingleInvoker::~SingleInvoker()
00192 {
00193     ExpressionVar::delStorage(storage_);
00194 }
00195 
00196 pair<edm::ObjectWithDict,bool>
00197 SingleInvoker::invoke(const edm::ObjectWithDict & o, std::vector<edm::ObjectWithDict> &v) const 
00198 {
00199     /* std::cerr << "[SingleInvoker::invoke] member " << invokers_.front().method().qualifiedName() << 
00200                                        " of type " << o.typeOf().qualifiedName() <<
00201                                        (!isRefGet_ ? " is one shot" : " needs another round") << std::endl; */
00202     pair<edm::ObjectWithDict,bool> ret(invokers_.front().invoke(o, storage_), !isRefGet_);
00203     if (storageNeedsDestructor_) {
00204         //std::cout << "Storage type: " << storage_.typeOf().qualifiedName() << ", I have to call the destructor." << std::endl;
00205         v.push_back(storage_);
00206     }
00207     return ret;
00208 }
00209 
00210 double
00211 SingleInvoker::retToDouble(const edm::ObjectWithDict & o) const {
00212     if (!ExpressionVar::isValidReturnType(retType_)) {
00213         throwFailedConversion(o);
00214     }
00215     return ExpressionVar::objToDouble(o, retType_);
00216 }
00217 
00218 void
00219 SingleInvoker::throwFailedConversion(const edm::ObjectWithDict & o) const {
00220     throw edm::Exception(edm::errors::Configuration)
00221         << "member \"" << invokers_.back().methodName()
00222         << "\" return type is \"" << invokers_.back().returnTypeName()
00223         << "\" retured a \"" << o.typeOf().name(edm::TypeNameHandling::Qualified)
00224         << "\" which is not convertible to double.";
00225 }