Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-04-06 12:13:13

0001 #ifndef FWCore_Utilities_ThreadSafeRegistry_h
0002 #define FWCore_Utilities_ThreadSafeRegistry_h
0003 
0004 #include <map>
0005 #include <vector>
0006 #include <ostream>
0007 #include <mutex>
0008 
0009 // ----------------------------------------------------------------------
0010 
0011 /// A ThreadSafeRegistry is used to keep track of the instances of
0012 /// some type 'value_typed'.  These objects are each associated with
0013 /// a given 'key_type' object, which must be retrievable from the
0014 /// value_type object, and which must uniquely identify the
0015 /// value_type's value.
0016 ///
0017 /// This class is sufficiently thread-safe to be usable in a
0018 /// thread-safe manner. Don't let  the name mislead you  into thinking
0019 /// it provides more guarantee than that!
0020 ///
0021 /// If 'm' is of type 'value_type const&', the expression
0022 ///
0023 ///    key_type k = m.id();
0024 ///
0025 ///  must be legal, and must return the unique key associated with
0026 ///  the value of 'm'.
0027 // ----------------------------------------------------------------------
0028 
0029 #pragma GCC visibility push(default)
0030 namespace edm {
0031   namespace detail {
0032 
0033     template <typename KEY, typename T>
0034     class ThreadSafeRegistry {
0035     public:
0036       typedef KEY key_type;
0037       typedef T value_type;
0038       typedef typename std::map<key_type, value_type> collection_type;
0039       typedef typename collection_type::size_type size_type;
0040 
0041       typedef typename std::vector<value_type> vector_type;
0042 
0043       static ThreadSafeRegistry* instance();
0044 
0045       // The following two are not implemented.
0046       ThreadSafeRegistry(ThreadSafeRegistry<KEY, T> const&) = delete;
0047 
0048       ThreadSafeRegistry<KEY, T>& operator=(ThreadSafeRegistry<KEY, T> const&) = delete;
0049 
0050       /// Retrieve the value_type object with the given key.
0051       /// If we return 'true', then 'result' carries the
0052       /// value_type object.
0053       /// If we return 'false, no matching key was found, and
0054       /// the value of 'result' is undefined.
0055       bool getMapped(key_type const& k, value_type& result) const;
0056 
0057       /** Retrieve a pointer to the value_type object with the given key.
0058        If there is no object associated with the given key 0 is returned.
0059        */
0060       value_type const* getMapped(key_type const& k) const;
0061 
0062       /// Insert the given value_type object into the
0063       /// registry. If there was already a value_type object
0064       /// with the same key, we don't change it. This should be OK,
0065       /// since it should have the same contents if the key is the
0066       /// same.  Return 'true' if we really added the new
0067       /// value_type object, and 'false' if the
0068       /// value_type object was already present.
0069       bool insertMapped(value_type const& v);
0070 
0071       /// put the value_type objects in the given collection
0072       /// into the registry.
0073       void insertCollection(collection_type const& c);
0074       void insertCollection(vector_type const& c);
0075 
0076       /// Return true if there are no contained value_type objects.
0077       bool empty() const;
0078 
0079       /// Return true if there are any contained value_type objects.
0080       bool notEmpty() const;
0081 
0082       /// Return the number of contained value_type objects.
0083       size_type size() const;
0084 
0085       /// Print the contents of this registry to the given ostream.
0086       void print(std::ostream& os) const;
0087 
0088     private:
0089       ThreadSafeRegistry();
0090       ~ThreadSafeRegistry();
0091 
0092       mutable std::mutex mutex_;
0093       collection_type data_;
0094     };
0095 
0096     template <typename KEY, typename T, typename E>
0097     inline std::ostream& operator<<(std::ostream& os, ThreadSafeRegistry<KEY, T> const& reg) {
0098       reg.print(os);
0099       return os;
0100     }
0101 
0102     template <typename KEY, typename T>
0103     void ThreadSafeRegistry<KEY, T>::insertCollection(collection_type const& c) {
0104       for (auto const& item : c) {
0105         insertMapped(item.second);
0106       }
0107     }
0108 
0109     template <typename KEY, typename T>
0110     void ThreadSafeRegistry<KEY, T>::insertCollection(vector_type const& c) {
0111       for (auto const& item : c) {
0112         insertMapped(item);
0113       }
0114     }
0115 
0116     template <typename KEY, typename T>
0117     inline bool ThreadSafeRegistry<KEY, T>::empty() const {
0118       std::lock_guard<std::mutex> guard(mutex_);
0119       return data_.empty();
0120     }
0121 
0122     template <typename KEY, typename T>
0123     inline bool ThreadSafeRegistry<KEY, T>::notEmpty() const {
0124       return !empty();
0125     }
0126 
0127     template <typename KEY, typename T>
0128     inline typename ThreadSafeRegistry<KEY, T>::size_type ThreadSafeRegistry<KEY, T>::size() const {
0129       std::lock_guard<std::mutex> guard(mutex_);
0130       return data_.size();
0131     }
0132 
0133     template <typename KEY, typename T>
0134     void ThreadSafeRegistry<KEY, T>::print(std::ostream& os) const {
0135       std::lock_guard<std::mutex> guard(mutex_);
0136       os << "Registry with " << size() << " entries\n";
0137       for (auto const& item : data_) {
0138         os << item.first << " " << item.second << '\n';
0139       }
0140     }
0141 
0142     template <typename KEY, typename T>
0143     ThreadSafeRegistry<KEY, T>::ThreadSafeRegistry() : data_() {}
0144 
0145     template <typename KEY, typename T>
0146     ThreadSafeRegistry<KEY, T>::~ThreadSafeRegistry() {}
0147 
0148   }  // namespace detail
0149 }  // namespace edm
0150 #pragma GCC visibility pop
0151 #endif  //  FWCore_Utilities_ThreadSafeRegistry_h