Back to home page

Project CMSSW displayed by LXR

 
 

    


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

0001 #ifndef CommonTools_Utils_MethodInvoker_h
0002 #define CommonTools_Utils_MethodInvoker_h
0003 
0004 #include "CommonTools/Utils/interface/parser/AnyMethodArgument.h"
0005 #include "CommonTools/Utils/interface/TypeCode.h"
0006 #include "FWCore/Reflection/interface/FunctionWithDict.h"
0007 #include "FWCore/Reflection/interface/MemberWithDict.h"
0008 #include "FWCore/Reflection/interface/ObjectWithDict.h"
0009 #include "FWCore/Utilities/interface/TypeID.h"
0010 
0011 #include <map>
0012 #include <vector>
0013 
0014 #include "oneapi/tbb/concurrent_unordered_map.h"
0015 #include "oneapi/tbb/concurrent_queue.h"
0016 
0017 namespace edm {
0018   struct TypeIDHasher {
0019     size_t operator()(TypeID const& tid) const { return std::hash<std::string>{}(std::string(tid.name())); }
0020   };
0021 }  // namespace edm
0022 
0023 namespace reco {
0024   namespace parser {
0025 
0026     class MethodInvoker {
0027     private:  // Private Data Members
0028       edm::FunctionWithDict method_;
0029       edm::MemberWithDict member_;
0030       std::vector<AnyMethodArgument> ints_;  // already fixed to the correct type
0031       std::vector<void*> args_;
0032 
0033       bool isFunction_;
0034       edm::TypeWithDict retTypeFinal_;
0035 
0036     private:  // Private Function Members
0037       void setArgs();
0038 
0039     public:  // Public Function Members
0040       explicit MethodInvoker(const edm::FunctionWithDict& method,
0041                              const std::vector<AnyMethodArgument>& ints = std::vector<AnyMethodArgument>());
0042       explicit MethodInvoker(const edm::MemberWithDict&);
0043       MethodInvoker(const MethodInvoker&);
0044       MethodInvoker& operator=(const MethodInvoker&);
0045 
0046       edm::FunctionWithDict const method() const { return method_; }
0047       edm::MemberWithDict const member() const { return member_; }
0048       bool isFunction() const { return isFunction_; }
0049       std::string methodName() const;
0050       std::string returnTypeName() const;
0051 
0052       /// Invokes the method, putting the result in retval.
0053       /// Returns the Object that points to the result value,
0054       /// after removing any "*" and "&"
0055       /// Caller code is responsible for allocating retstore
0056       /// before calling 'invoke', and of deallocating it afterwards
0057       edm::ObjectWithDict invoke(const edm::ObjectWithDict& obj, edm::ObjectWithDict& retstore) const;
0058     };
0059 
0060     struct SingleInvoker;
0061 
0062     //Handles temporary object storage
0063     struct StorageManager {
0064     private:
0065       edm::ObjectWithDict object_;
0066       SingleInvoker const* invoker_;
0067       bool needsDestructor_;
0068 
0069     public:
0070       StorageManager(edm::ObjectWithDict const& iObj, SingleInvoker const* iInvoker, bool iNeedsDestructor_)
0071           : object_(iObj), invoker_(iInvoker), needsDestructor_(iNeedsDestructor_) {}
0072 
0073       StorageManager(const StorageManager&) = delete;
0074       StorageManager(StorageManager&& iOther)
0075           : object_(iOther.object_), invoker_(iOther.invoker_), needsDestructor_(iOther.needsDestructor_) {
0076         iOther.needsDestructor_ = false;
0077         iOther.invoker_ = nullptr;
0078       }
0079       StorageManager& operator=(const StorageManager&) = delete;
0080       StorageManager& operator=(StorageManager&&) = delete;
0081 
0082       ~StorageManager();
0083     };
0084     /// A bigger brother of the MethodInvoker:
0085     /// - it owns also the object in which to store the result
0086     /// - it handles by itself the popping out of Refs and Ptrs
0087     /// in this way, it can map 1-1 to a name and set of args
0088     struct SingleInvoker {
0089     private:  // Private Data Members
0090       method::TypeCode retType_;
0091       std::vector<MethodInvoker> invokers_;
0092       mutable oneapi::tbb::concurrent_queue<edm::ObjectWithDict> storage_;
0093       bool storageNeedsDestructor_;
0094       /// true if this invoker just pops out a ref and returns (ref.get(), false)
0095       bool isRefGet_;
0096 
0097       edm::ObjectWithDict borrowStorage() const;
0098 
0099       edm::ObjectWithDict createStorage(bool& needsDestructor) const;
0100 
0101     public:
0102       SingleInvoker(const SingleInvoker&) = delete;
0103       SingleInvoker& operator=(const SingleInvoker&) = delete;
0104 
0105       SingleInvoker(const edm::TypeWithDict&, const std::string& name, const std::vector<AnyMethodArgument>& args);
0106       ~SingleInvoker();
0107 
0108       /// If the member is found in object o, evaluate and
0109       /// return (value,true)
0110       /// If the member is not found but o is a Ref/RefToBase/Ptr,
0111       /// (return o.get(), false)
0112       /// the actual edm::ObjectWithDict where the result is stored
0113       /// will be pushed in vector so that, if needed, its destructor
0114       /// can be called
0115       std::pair<edm::ObjectWithDict, bool> invoke(const edm::ObjectWithDict& o, std::vector<StorageManager>& v) const;
0116 
0117       /// convert the output of invoke to a double, if possible
0118       double retToDouble(const edm::ObjectWithDict&) const;
0119 
0120       void throwFailedConversion(const edm::ObjectWithDict&) const;
0121 
0122       void returnStorage(edm::ObjectWithDict&&) const;
0123     };
0124 
0125     /// Keeps different SingleInvokers for each dynamic type of the objects passed to invoke()
0126     struct LazyInvoker {
0127       typedef std::shared_ptr<SingleInvoker> SingleInvokerPtr;
0128       typedef tbb::concurrent_unordered_map<edm::TypeID, SingleInvokerPtr, edm::TypeIDHasher> InvokerMap;
0129 
0130     private:  // Private Data Members
0131       std::string name_;
0132       std::vector<AnyMethodArgument> argsBeforeFixups_;
0133       // the shared ptr is only to make the code exception safe
0134       // otherwise I think it could leak if the constructor of
0135       // SingleInvoker throws an exception (which can happen)
0136       mutable InvokerMap invokers_;
0137 
0138     private:  // Private Function Members
0139       const SingleInvoker& invoker(const edm::TypeWithDict&) const;
0140 
0141     public:  // Public Function Members
0142       explicit LazyInvoker(const std::string& name, const std::vector<AnyMethodArgument>& args);
0143       ~LazyInvoker();
0144 
0145       /// invoke method, returns object that points to result
0146       /// (after stripping '*' and '&')
0147       /// the object is still owned by the LazyInvoker
0148       /// the actual edm::ObjectWithDict where the result is
0149       /// stored will be pushed in vector
0150       /// so that, if needed, its destructor can be called
0151       edm::ObjectWithDict invoke(const edm::ObjectWithDict& o, std::vector<StorageManager>& v) const;
0152 
0153       /// invoke and coerce result to double
0154       double invokeLast(const edm::ObjectWithDict& o, std::vector<StorageManager>& v) const;
0155     };
0156 
0157   }  // namespace parser
0158 }  // namespace reco
0159 
0160 #endif  // CommonTools_Utils_MethodInvoker_h