Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-04-06 12:05:02

0001 #ifndef DataFormats_Provenance_ProductResolverIndexHelper_h
0002 #define DataFormats_Provenance_ProductResolverIndexHelper_h
0003 
0004 /** \class edm::ProductResolverIndexHelper
0005 
0006 This class assigns and gets the ProductResolverIndex
0007 associated with a type, module label, instance, and
0008 process.  The ProductResolverIndex is used to tell the
0009 Principal where to store a ProductResolver and how to find
0010 it quickly.
0011 
0012 One can also look up the same ProductResolverIndex's using
0013 the type or base type of an element in a container in the
0014 product (if the product is a container). In this case the
0015 KindOfType argument to the Principal::getByLabel function
0016 is ELEMENT_TYPE, whereas normally it is PRODUCT_TYPE.
0017 
0018 There are also special ProductResolverIndex's generated
0019 where the process name is empty. These indexes refer
0020 to a special ProductResolvers that search for a matching
0021 product from the most recent process that has a matching
0022 type, label and instance. There is ProductResolverIndex
0023 generated for each type/label/instance combination which
0024 has at least one entry in the tables in this class.
0025 Both PRODUCT_TYPEs and ELEMENT_TYPEs get these special
0026 ProductResolvers.
0027 
0028 The ProductResolverIndex for a particular product
0029 will not change during a process after the ProductRegistry
0030 has been frozen. Nor will any of the other member data
0031 of this class. Multiple threads can access it concurrently
0032 without problems. The ProductResolverIndexes can be safely
0033 cached in InputTags and possibly other places, because
0034 they never change within a process. The ProductResolverIndex
0035 for a particular product is not intended to be persistent
0036 and will be different in different processes.
0037 
0038 The ProductResolverIndex is used to order the placement of
0039 the ProductResolvers in the Principal that are either
0040 present in the input or produced in the current process.
0041 Be aware that there are other ProductResolvers for products
0042 that come after ProductResolvers placed by this class.
0043 For example, the placement of dropped products
0044 is not handled by this class, instead by the ProductRegistry.
0045 The reason for this distinction is that those other
0046 ProductResolvers can change and be added as a process runs.
0047 The content of this class never changes after the
0048 ProductRegistry is frozen.
0049 
0050 \author W. David Dagenhart, created 10 December, 2012 
0051 
0052 */
0053 
0054 #include "FWCore/Utilities/interface/ProductResolverIndex.h"
0055 #include "FWCore/Utilities/interface/ProductKindOfType.h"
0056 #include "FWCore/Utilities/interface/TypeID.h"
0057 #include "FWCore/Utilities/interface/propagate_const.h"
0058 
0059 #include <iosfwd>
0060 #include <memory>
0061 #include <set>
0062 #include <string>
0063 #include <vector>
0064 #include <tuple>
0065 #include <unordered_map>
0066 
0067 namespace edm {
0068 
0069   class TypeWithDict;
0070 
0071   namespace productholderindexhelper {
0072     // The next function supports views. For the given wrapped type,
0073     // which must be Wrapper<T>,
0074     // this function returns the type of the contained type of T.
0075     // If the type is not a recongnized container, it returns
0076     // a TypeID(typeid(void)).
0077     TypeID getContainedTypeFromWrapper(TypeID const& wrappedtypeID, std::string const& className);
0078 
0079     // The next function supports views. For the given type T,
0080     // this function returns the type of the contained type of T.
0081     // If the type is not a recongnized container, it returns
0082     // a TypeID(typeid(void)).
0083     // This calls getContainedTypefromWrapped internally
0084     // If the TypeID for the wrapped type is already available,
0085     // it is faster to call getContainedTypeFromWrapper directly.
0086     TypeID getContainedType(TypeID const& typeID);
0087 
0088     bool typeIsViewCompatible(TypeID const& requestedViewType,
0089                               TypeID const& wrappedtypeID,
0090                               std::string const& className);
0091   }  // namespace productholderindexhelper
0092 
0093   class ProductResolverIndexHelper {
0094   public:
0095     ProductResolverIndexHelper();
0096 
0097     // The accessors below return a ProductResolverIndex that matches
0098     // the arguments or a set of matching indexes using the Matches
0099     // class. A returned index can have a value that indicates that it
0100     // is invalid or ambiguous and the client should check for these
0101     // values before using the index (see ProductResolverIndex.h).
0102 
0103     // If no matches are found or the ProductResolverIndexHelper
0104     // has not been frozen yet, then an invalid index or a Matches
0105     // object with numberOfMatches equal to 0 will be returned.
0106 
0107     // The ambiguous values can occur when the kind of type is ELEMENT_TYPE
0108     // type. ELEMENT_TYPE is the type or base type of an object
0109     // stored in a container that is the product. These types are used
0110     // with data requests that use Views. For PRODUCT_TYPE types, ambiguity
0111     // is not possible.
0112 
0113     // The next function returns the index for the one group that
0114     // matches the type, module label, instance, and process.
0115     // The 3 pointer arguments must point to C style strings terminated
0116     // by a '\0' with the one following possible exception. If the
0117     // process pointer is null or the process string empty, then
0118     // this returns the index of the special ProductResolver that
0119     // knows how to search for the product matching the type, module
0120     // label, and instance and which is from the most recent process.
0121     ProductResolverIndex index(KindOfType kindOfType,
0122                                TypeID const& typeID,
0123                                char const* moduleLabel,
0124                                char const* instance,
0125                                char const* process = nullptr) const;
0126 
0127     using ModulesToIndiciesMap =
0128         std::unordered_multimap<std::string, std::tuple<TypeID const*, const char*, ProductResolverIndex>>;
0129     ModulesToIndiciesMap indiciesForModulesInProcess(const std::string& iProcessName) const;
0130 
0131     class Matches {
0132     public:
0133       Matches(ProductResolverIndexHelper const* productResolverIndexHelper,
0134               unsigned int startInIndexAndNames,
0135               unsigned int numberOfMatches);
0136 
0137       ProductResolverIndex index(unsigned int i) const;
0138       unsigned int numberOfMatches() const { return numberOfMatches_; }
0139       char const* moduleLabel(unsigned int i) const;
0140       char const* productInstanceName(unsigned int i) const;
0141       char const* processName(unsigned int i) const;
0142 
0143     private:
0144       ProductResolverIndexHelper const* productResolverIndexHelper_;
0145       unsigned int startInIndexAndNames_;
0146       unsigned int numberOfMatches_;
0147     };
0148 
0149     // Return ProductResolverIndex's for all product holders that
0150     // match the type, module label, and product instance name.
0151     // The pointer arguments must be C style strings terminated
0152     // by a '\0'.
0153     Matches relatedIndexes(KindOfType kindOfType,
0154                            TypeID const& typeID,
0155                            char const* moduleLabel,
0156                            char const* instance) const;
0157 
0158     // Return indexes for all groups that match the type.
0159     Matches relatedIndexes(KindOfType kindOfType, TypeID const& typeID) const;
0160 
0161     // This will throw if called after the object is frozen.
0162     // The typeID must be for a type with a dictionary
0163     // (the calling function is expected to check that)
0164     // The pointer arguments must point at C style strings
0165     // terminated by '\0'.
0166     // 1. This creates an entry and new ProductResolverIndex for
0167     // the product if it does not already exist. If it
0168     // does exist then it throws.
0169     // 2. If it does not already exist, this will create an
0170     // entry and new ProductResolverIndex for the ProductResolver
0171     // that will search for the matching type, label, and
0172     // instance for the most recent process (internally indicated
0173     // by an empty process string).
0174     // This will then loop over the contained class (if it exists)
0175     // and the base classes of the contained class.
0176     // 1. If the matching type, label, instance, and process
0177     // already exist then that entry is modified and marked
0178     // ambiguous. If not, it inserts an entry which uses the same
0179     // ProductResolverIndex as the containing product.
0180     // 2. If it does not already exist it inserts a new
0181     // entry with a new ProductResolverIndex for the case
0182     // which searches for the most recent process.
0183     ProductResolverIndex insert(TypeID const& typeID,
0184                                 char const* moduleLabel,
0185                                 char const* instance,
0186                                 char const* process,
0187                                 TypeID const& containedTypeID,
0188                                 std::vector<TypeID>* baseTypesOfContainedType);
0189 
0190     ProductResolverIndex insert(TypeID const& typeID,
0191                                 char const* moduleLabel,
0192                                 char const* instance,
0193                                 char const* process);
0194 
0195     // Before the object is frozen the accessors above will
0196     // fail to find a match. Once frozen, no more new entries
0197     // can be added with insert.
0198     void setFrozen();
0199 
0200     std::vector<std::string> const& lookupProcessNames() const;
0201 
0202     class Range {
0203     public:
0204       Range(unsigned int begin, unsigned int end) : begin_(begin), end_(end) {}
0205       unsigned int begin() const { return begin_; }
0206       unsigned int end() const { return end_; }
0207 
0208     private:
0209       unsigned int begin_;
0210       unsigned int end_;
0211     };
0212 
0213     class IndexAndNames {
0214     public:
0215       IndexAndNames(ProductResolverIndex index, unsigned int start, unsigned int startProcess)
0216           : index_(index), startInBigNamesContainer_(start), startInProcessNames_(startProcess) {}
0217       ProductResolverIndex index() const { return index_; }
0218       unsigned int startInBigNamesContainer() const { return startInBigNamesContainer_; }
0219       unsigned int startInProcessNames() const { return startInProcessNames_; }
0220 
0221     private:
0222       ProductResolverIndex index_;
0223       unsigned int startInBigNamesContainer_;
0224       unsigned int startInProcessNames_;
0225     };
0226 
0227     unsigned int beginElements() const { return beginElements_; }
0228     std::vector<TypeID> const& sortedTypeIDs() const { return sortedTypeIDs_; }
0229     std::vector<Range> const& ranges() const { return ranges_; }
0230     std::vector<IndexAndNames> const& indexAndNames() const { return indexAndNames_; }
0231     std::vector<char> const& processNames() const { return processNames_; }
0232 
0233     // The next few functions are intended for internal use
0234     // but are public so tests can use them also.
0235 
0236     unsigned int indexToIndexAndNames(KindOfType kindOfType,
0237                                       TypeID const& typeID,
0238                                       char const* moduleLabel,
0239                                       char const* instance,
0240                                       char const* process) const;
0241 
0242     // Returns the index into sortedTypeIDs_. Returns the maximum unsigned
0243     // int value if the type is not there.
0244     unsigned int indexToType(KindOfType kindOfType, TypeID const& typeID) const;
0245 
0246     // Returns the index of the process name in processNames_. Returns the
0247     // maximum unsigned int value if the process name is not found.
0248     unsigned int processIndex(char const* process) const;
0249 
0250     // This will throw if it detects problems, but unless there is a bug
0251     // there should never be any. Mostly it is checking for things which
0252     // might cause out of bounds errors when accessing the vectors.
0253     void sanityCheck() const;
0254 
0255     ProductResolverIndex nextIndexValue() const { return nextIndexValue_; }
0256 
0257     // For debugging only
0258     void print(std::ostream& os) const;
0259 
0260   private:
0261     // Next available value for a ProductResolverIndex. This just
0262     // increments by one each time a new value is assigned.
0263     ProductResolverIndex nextIndexValue_;
0264 
0265     // This is an index into sortedTypeIDs_ that tells where
0266     // the entries corresponding to types of elements in containers
0267     // start.
0268     unsigned int beginElements_;
0269 
0270     // Sorted by putting all the product entries first and
0271     // then the element entries.  Then sorted by TypeID value.
0272     // Most lookups start here by finding the TypeID and
0273     // then using its position to find the corresponding Range
0274     // in the ranges_ vector below.
0275     std::vector<TypeID> sortedTypeIDs_;
0276 
0277     // There is a one to one correspondence between this vector
0278     // and sortedTypeIDs_ and the corresponding elements appear
0279     // in the same order. Each Range object holds the beginning and
0280     // end of the corresponding elements in the indexAndNames_
0281     // vector below.
0282     std::vector<Range> ranges_;
0283 
0284     // Each element of this vector contains a ProductResolverIndex.
0285     // It also contains indexes into vectors of characters that
0286     // hold the corresponding moduleLabel, instance, and process
0287     // name. Note this is sorted with product entries first then
0288     // element entries, then by TypeID, then by moduleLabel,
0289     // then by instance, and finally by process. Note that in
0290     // a subset of entries that have matching type/label/instance
0291     // the entry with an empty process name will always be the
0292     // first process and startInProcessNames_ will always be 0
0293     // for the empty process name.
0294     std::vector<IndexAndNames> indexAndNames_;
0295 
0296     // These contain C style strings terminated
0297     // by '\0' all concatenated together. In the
0298     // first vector the strings come in pairs,
0299     // always module label then instance.  The pairs
0300     // are ordered the same as the IndexAndNames
0301     // vector. Within a TypeID, the moduleLabel/instance
0302     // pair is not duplicated if it appears multiple times.
0303     // The second vector contains all the process names
0304     // in alphabetical order with no duplication. The
0305     // first element is always the empty string.
0306     std::vector<char> bigNamesContainer_;
0307     std::vector<char> processNames_;
0308 
0309     // Duplicates the entries in processNames_ in
0310     // a convenient format.
0311     std::vector<std::string> lookupProcessNames_;
0312 
0313     // The rest of the data members are for temporary use
0314     // while the data structure is being filled.
0315 
0316     class Item {
0317     public:
0318       Item(KindOfType kindOfType,
0319            TypeID const& typeID,
0320            std::string const& moduleLabel,
0321            std::string const& instance,
0322            std::string const& process,
0323            ProductResolverIndex index);
0324       KindOfType kindOfType() const { return kindOfType_; }
0325       TypeID const& typeID() const { return typeID_; }
0326       std::string const& moduleLabel() const { return moduleLabel_; }
0327       std::string const& instance() const { return instance_; }
0328       std::string const& process() const { return process_; }
0329       ProductResolverIndex index() const { return index_; }
0330 
0331       void clearProcess() { process_.clear(); }
0332       void setIndex(ProductResolverIndex v) { index_ = v; }
0333 
0334       bool operator<(Item const& right) const;
0335 
0336     private:
0337       KindOfType kindOfType_;
0338       TypeID typeID_;
0339       std::string moduleLabel_;
0340       std::string instance_;
0341       std::string process_;
0342       ProductResolverIndex index_;
0343     };
0344 
0345     edm::propagate_const<std::unique_ptr<std::set<Item>>> items_;
0346 
0347     edm::propagate_const<std::unique_ptr<std::set<std::string>>> processItems_;
0348   };
0349 }  // namespace edm
0350 #endif