Back to home page

Project CMSSW displayed by LXR

 
 

    


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     // just delete a void*, as that's what it was
0060     void** p = static_cast<void**>(obj.address());
0061     delete p;
0062   } else {
0063     //std::cout << "Calling Destruct on a " <<
0064     //  obj.typeOf().qualifiedName() << std::endl;
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     // in this case, I have to allocate a void*, not an object!
0076     obj = edm::ObjectWithDict(retType, new void*);
0077   } else {
0078     obj = edm::ObjectWithDict(retType, retType.allocate());
0079     ret = retType.isClass();
0080     //std::cout << "MethodChain: reserved memory at "  << obj.address() <<
0081     //  " for a " << retType.qualifiedName() << " returned by " <<
0082     //  member.name() << std::endl;
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 }