Back to home page

Project CMSSW displayed by LXR

 
 

    


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

0001 #ifndef DDI_Store_h
0002 #define DDI_Store_h
0003 
0004 #include <map>
0005 #include "DetectorDescription/Core/interface/rep_type.h"
0006 #include "FWCore/MessageLogger/interface/MessageLogger.h"
0007 
0008 //;
0009 //FIXME: Store : implement readOnly-behaviour ..
0010 namespace DDI {
0011 
0012   /** 
0013       A Store provides a place for objects of type I which are uniquely identified
0014       by there name of type N. The objects themselves can be accessed indirectly
0015       by the prep_type of the Store like
0016       
0017       typedef Store<std::string,double> NamedDouble;
0018       NamedDouble::prep_type d = NamedDouble("Four", new double(4.));
0019       double val  = *(d->second);
0020       std::string name = d->first;
0021       
0022       K is the key_type which is used as an index in the storage.
0023       It must fulfill all requirements for a key in a sorted associative container.
0024       N is the user-friendly name_type, which must be mapped uniquely
0025       to the key_type and vice versa. N itself must also fulfill all requirements
0026       of a key in a sorted associative container.
0027       The reason to provide K is that one might save some memory by compacting
0028       common parts of information contained in different instances of N, e.g.
0029       if N is a pair<string,string>, the first string being a 'namespace' the 
0030       second a 'name' then K could be a pair<int,string> thus compacting the
0031       namespace-string to a simple int.
0032       K and N must support following unique conversions:
0033       - from N to K, thus N(const K &)
0034       - from K to N, thus K(const N &)
0035   */
0036   template <class N, class I, class K = I>
0037   class Store {
0038   public:
0039     using name_type = N;
0040     using pimpl_type = I;
0041     using key_type = K;
0042     using Rep_type = rep_type<name_type, pimpl_type>;
0043     using prep_type = Rep_type*;
0044     using registry_type = std::map<name_type, prep_type>;
0045     using iterator = typename registry_type::iterator;
0046 
0047     auto begin() { return reg_.begin(); }
0048     auto end() { return reg_.end(); }
0049     auto size() const { return reg_.size(); }
0050 
0051     // empty shell or fetch from registry
0052     prep_type create(const name_type&);
0053 
0054     // full new object or replace existing with new one
0055     prep_type create(const name_type&, pimpl_type);
0056 
0057     // clear all objects
0058     void clear();
0059 
0060     // swap moves the registry from this guy to another of the same type
0061     void swap(Store&);
0062 
0063     bool isDefined(const name_type& n) const;
0064     void setReadOnly(bool b) { readOnly_ = b; }
0065     bool readOnly() const { return readOnly_; }
0066 
0067     Store() : readOnly_(false) {}
0068     ~Store();
0069     Store(const Store&) = delete;
0070     Store& operator=(const Store&) = delete;
0071 
0072   protected:
0073     std::map<name_type, prep_type> reg_;
0074     bool readOnly_;
0075   };
0076 
0077   template <class N, class I, class K>
0078   typename Store<N, I, K>::prep_type Store<N, I, K>::create(const name_type& n) {
0079     prep_type tmp = nullptr;
0080     auto result = reg_.emplace(n, tmp);
0081     if (result.second) {
0082       if (readOnly_)
0083         throw cms::Exception("DetectorDescriptionStore")
0084             << " Store has been locked. Illegal attempt to add " << n << " to a global store.";
0085       // ELSE
0086       result.first->second = new Rep_type(n, nullptr);
0087     }
0088     return result.first->second;
0089   }
0090 
0091   template <class N, class I, class K>
0092   typename Store<N, I, K>::prep_type Store<N, I, K>::create(const name_type& n, pimpl_type p) {
0093     if (readOnly_)
0094       throw cms::Exception("DetectorDescriptionStore")
0095           << " Store has been locked. Illegal attempt to add " << n << " to a global store.";
0096     // ELSE
0097     prep_type tmp = nullptr;
0098     auto result = reg_.emplace(n, tmp);
0099     if (!result.second) {
0100       result.first->second->second.swap(p);
0101     } else {
0102       result.first->second = new Rep_type(n, std::move(p));
0103     }
0104     return result.first->second;
0105   }
0106 
0107   template <typename I>
0108   struct Finalize {
0109     static void cleanup(I&& ptr) {}
0110   };
0111 
0112   template <typename I>
0113   struct Finalize<I*> {
0114     static void cleanup(I* ptr) {
0115       delete ptr;
0116       ptr = nullptr;
0117     }
0118   };
0119 
0120   template <class N, class I, class K>
0121   Store<N, I, K>::~Store() {
0122     for (auto it : reg_) {
0123       Finalize<I>::cleanup(std::move(it.second->second));
0124       delete it.second;
0125       it.second = nullptr;
0126     }
0127   }
0128 
0129   template <class N, class I, class K>
0130   bool Store<N, I, K>::isDefined(const name_type& n) const {
0131     if (readOnly_)
0132       edm::LogWarning("DetectorDescriptionStore")
0133           << " Store is locked and most likely empty.  isDefined will be false.";
0134     auto it = reg_.find(n);
0135     bool result(false);
0136     if (it != reg_.end()) {
0137       if (it.second->second) {
0138         result = true;
0139       }
0140     }
0141     return result;
0142   }
0143 
0144   template <class N, class I, class K>
0145   void Store<N, I, K>::swap(Store<N, I, K>& storeToSwap) {
0146     reg_.swap(storeToSwap.reg_);
0147     storeToSwap.readOnly_ = readOnly_;
0148   }
0149 
0150 }  // namespace DDI
0151 
0152 #endif