Finalize

Finalize

Store

Macros

Line Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152
#ifndef DDI_Store_h
#define DDI_Store_h

#include <map>
#include "DetectorDescription/Core/interface/rep_type.h"
#include "FWCore/MessageLogger/interface/MessageLogger.h"

//;
//FIXME: Store : implement readOnly-behaviour ..
namespace DDI {

  /** 
      A Store provides a place for objects of type I which are uniquely identified
      by there name of type N. The objects themselves can be accessed indirectly
      by the prep_type of the Store like
      
      typedef Store<std::string,double> NamedDouble;
      NamedDouble::prep_type d = NamedDouble("Four", new double(4.));
      double val  = *(d->second);
      std::string name = d->first;
      
      K is the key_type which is used as an index in the storage.
      It must fulfill all requirements for a key in a sorted associative container.
      N is the user-friendly name_type, which must be mapped uniquely
      to the key_type and vice versa. N itself must also fulfill all requirements
      of a key in a sorted associative container.
      The reason to provide K is that one might save some memory by compacting
      common parts of information contained in different instances of N, e.g.
      if N is a pair<string,string>, the first string being a 'namespace' the 
      second a 'name' then K could be a pair<int,string> thus compacting the
      namespace-string to a simple int.
      K and N must support following unique conversions:
      - from N to K, thus N(const K &)
      - from K to N, thus K(const N &)
  */
  template <class N, class I, class K = I>
  class Store {
  public:
    using name_type = N;
    using pimpl_type = I;
    using key_type = K;
    using Rep_type = rep_type<name_type, pimpl_type>;
    using prep_type = Rep_type*;
    using registry_type = std::map<name_type, prep_type>;
    using iterator = typename registry_type::iterator;

    auto begin() { return reg_.begin(); }
    auto end() { return reg_.end(); }
    auto size() const { return reg_.size(); }

    // empty shell or fetch from registry
    prep_type create(const name_type&);

    // full new object or replace existing with new one
    prep_type create(const name_type&, pimpl_type);

    // clear all objects
    void clear();

    // swap moves the registry from this guy to another of the same type
    void swap(Store&);

    bool isDefined(const name_type& n) const;
    void setReadOnly(bool b) { readOnly_ = b; }
    bool readOnly() const { return readOnly_; }

    Store() : readOnly_(false) {}
    ~Store();
    Store(const Store&) = delete;
    Store& operator=(const Store&) = delete;

  protected:
    std::map<name_type, prep_type> reg_;
    bool readOnly_;
  };

  template <class N, class I, class K>
  typename Store<N, I, K>::prep_type Store<N, I, K>::create(const name_type& n) {
    prep_type tmp = nullptr;
    auto result = reg_.emplace(n, tmp);
    if (result.second) {
      if (readOnly_)
        throw cms::Exception("DetectorDescriptionStore")
            << " Store has been locked. Illegal attempt to add " << n << " to a global store.";
      // ELSE
      result.first->second = new Rep_type(n, nullptr);
    }
    return result.first->second;
  }

  template <class N, class I, class K>
  typename Store<N, I, K>::prep_type Store<N, I, K>::create(const name_type& n, pimpl_type p) {
    if (readOnly_)
      throw cms::Exception("DetectorDescriptionStore")
          << " Store has been locked. Illegal attempt to add " << n << " to a global store.";
    // ELSE
    prep_type tmp = nullptr;
    auto result = reg_.emplace(n, tmp);
    if (!result.second) {
      result.first->second->second.swap(p);
    } else {
      result.first->second = new Rep_type(n, std::move(p));
    }
    return result.first->second;
  }

  template <typename I>
  struct Finalize {
    static void cleanup(I&& ptr) {}
  };

  template <typename I>
  struct Finalize<I*> {
    static void cleanup(I* ptr) {
      delete ptr;
      ptr = nullptr;
    }
  };

  template <class N, class I, class K>
  Store<N, I, K>::~Store() {
    for (auto it : reg_) {
      Finalize<I>::cleanup(std::move(it.second->second));
      delete it.second;
      it.second = nullptr;
    }
  }

  template <class N, class I, class K>
  bool Store<N, I, K>::isDefined(const name_type& n) const {
    if (readOnly_)
      edm::LogWarning("DetectorDescriptionStore")
          << " Store is locked and most likely empty.  isDefined will be false.";
    auto it = reg_.find(n);
    bool result(false);
    if (it != reg_.end()) {
      if (it.second->second) {
        result = true;
      }
    }
    return result;
  }

  template <class N, class I, class K>
  void Store<N, I, K>::swap(Store<N, I, K>& storeToSwap) {
    reg_.swap(storeToSwap.reg_);
    storeToSwap.readOnly_ = readOnly_;
  }

}  // namespace DDI

#endif