00001 #ifndef FWCore_Utilities_ThreadSafeRegistry_h
00002 #define FWCore_Utilities_ThreadSafeRegistry_h
00003
00004 #include <map>
00005 #include <vector>
00006 #include "boost/thread.hpp"
00007
00008
00009
00026
00027
00028 namespace edm {
00029 namespace detail {
00030 struct empty { };
00031
00032 template <typename KEY, typename T, typename E=empty>
00033 class ThreadSafeRegistry {
00034 public:
00035 typedef KEY key_type;
00036 typedef T value_type;
00037 typedef E extra_type;
00038 typedef typename std::map<key_type, value_type> collection_type;
00039 typedef typename collection_type::size_type size_type;
00040
00041 typedef typename collection_type::const_iterator const_iterator;
00042
00043 typedef typename std::vector<value_type> vector_type;
00044
00045 static ThreadSafeRegistry* instance();
00046
00052 bool getMapped(key_type const& k, value_type& result) const;
00053
00057 value_type const* getMapped(key_type const& k) const;
00058
00066 bool insertMapped(value_type const& v);
00067
00070 void insertCollection(collection_type const& c);
00071 void insertCollection(vector_type const& c);
00072
00074 bool empty() const;
00075
00077 bool notEmpty() const;
00078
00080 size_type size() const;
00081
00084 const_iterator begin() const;
00085 const_iterator end() const;
00086
00088 void print(std::ostream& os) const;
00089
00091 collection_type& data();
00092 collection_type const& data() const;
00093
00097 extra_type& extra();
00098 extra_type const& extra() const;
00099
00100 private:
00101 ThreadSafeRegistry();
00102 ~ThreadSafeRegistry();
00103
00104
00105 ThreadSafeRegistry(ThreadSafeRegistry<KEY,T,E> const&);
00106
00107 ThreadSafeRegistry<KEY,T,E>&
00108 operator= (ThreadSafeRegistry<KEY,T,E> const&);
00109
00110 collection_type data_;
00111 extra_type extra_;
00112
00113 static ThreadSafeRegistry* instance_;
00114
00115 static boost::mutex registry_mutex;
00116 };
00117
00118 template <typename KEY, typename T, typename E>
00119 inline
00120 std::ostream&
00121 operator<< (std::ostream& os, ThreadSafeRegistry<KEY,T,E> const& reg) {
00122 reg.print(os);
00123 return os;
00124 }
00125
00126
00127
00128
00129
00130 template <typename KEY, typename T, typename E>
00131 ThreadSafeRegistry<KEY,T,E>* ThreadSafeRegistry<KEY,T,E>::instance_ = 0;
00132
00133 template <typename KEY, typename T, typename E>
00134 boost::mutex ThreadSafeRegistry<KEY,T,E>::registry_mutex;
00135
00136
00137
00138 template <typename KEY, typename T, typename E>
00139 ThreadSafeRegistry<KEY,T,E>*
00140 ThreadSafeRegistry<KEY,T,E>::instance() {
00141 if (instance_ == 0) {
00142 boost::mutex::scoped_lock lock(registry_mutex);
00143 if (instance_ == 0) {
00144 static ThreadSafeRegistry<KEY,T,E> me;
00145 instance_ = &me;
00146 }
00147 }
00148 return instance_;
00149 }
00150
00151 template <typename KEY, typename T, typename E>
00152 bool
00153 ThreadSafeRegistry<KEY,T,E>::getMapped(key_type const& k, value_type& result) const {
00154 bool found;
00155 const_iterator i;
00156 {
00157
00158
00159 boost::mutex::scoped_lock lock(registry_mutex);
00160 i = data_.find(k);
00161 found = (i != data_.end());
00162 }
00163 if (found) result = i->second;
00164 return found;
00165 }
00166
00167 template <typename KEY, typename T, typename E>
00168 typename ThreadSafeRegistry<KEY,T,E>::value_type const*
00169 ThreadSafeRegistry<KEY,T,E>::getMapped(key_type const& k) const {
00170 bool found;
00171 const_iterator i;
00172 {
00173
00174
00175 boost::mutex::scoped_lock lock(registry_mutex);
00176 i = data_.find(k);
00177 found = (i != data_.end());
00178 }
00179 return found ? &(i->second) : static_cast<value_type const*> (0);
00180 }
00181
00182 template <typename KEY, typename T, typename E>
00183 bool
00184 ThreadSafeRegistry<KEY,T,E>::insertMapped(value_type const& v) {
00185 bool newly_added = false;
00186 boost::mutex::scoped_lock lock(registry_mutex);
00187
00188 key_type id = v.id();
00189 if (data_.find(id) == data_.end()) {
00190 data_[id] = v;
00191 newly_added = true;
00192 }
00193 return newly_added;
00194 }
00195
00196 template <typename KEY, typename T, typename E>
00197 void
00198 ThreadSafeRegistry<KEY,T,E>::insertCollection(collection_type const& c) {
00199 for (typename collection_type::const_iterator it = c.begin(), itEnd = c.end(); it != itEnd; ++it) {
00200 insertMapped(it->second);
00201 }
00202 }
00203
00204 template <typename KEY, typename T, typename E>
00205 void
00206 ThreadSafeRegistry<KEY,T,E>::insertCollection(vector_type const& c) {
00207 for (typename vector_type::const_iterator it = c.begin(), itEnd = c.end(); it != itEnd; ++it) {
00208 insertMapped(*it);
00209 }
00210 }
00211
00212 template <typename KEY, typename T, typename E>
00213 inline
00214 bool
00215 ThreadSafeRegistry<KEY,T,E>::empty() const {
00216 return data_.empty();
00217 }
00218
00219 template <typename KEY, typename T, typename E>
00220 inline
00221 bool
00222 ThreadSafeRegistry<KEY,T,E>::notEmpty() const {
00223 return !empty();
00224 }
00225
00226 template <typename KEY, typename T, typename E>
00227 inline
00228 typename ThreadSafeRegistry<KEY,T,E>::size_type
00229 ThreadSafeRegistry<KEY,T,E>::size() const {
00230 return data_.size();
00231 }
00232
00233 template <typename KEY, typename T, typename E>
00234 inline
00235 typename ThreadSafeRegistry<KEY,T,E>::const_iterator
00236 ThreadSafeRegistry<KEY,T,E>::begin() const {
00237 return data_.begin();
00238 }
00239
00240 template <typename KEY, typename T, typename E>
00241 inline
00242 typename ThreadSafeRegistry<KEY,T,E>::const_iterator
00243 ThreadSafeRegistry<KEY,T,E>::end() const {
00244 return data_.end();
00245 }
00246
00247 template <typename KEY, typename T, typename E>
00248 void
00249 ThreadSafeRegistry<KEY,T,E>::print(std::ostream& os) const {
00250 os << "Registry with " << size() << " entries\n";
00251 for (const_iterator i=begin(), e=end(); i!=e; ++i) {
00252 os << i->first << " " << i->second << '\n';
00253 }
00254 }
00255
00256 template <typename KEY, typename T, typename E>
00257 inline
00258 typename ThreadSafeRegistry<KEY,T,E>::collection_type&
00259 ThreadSafeRegistry<KEY,T,E>::data() {
00260 return data_;
00261 }
00262
00263 template <typename KEY, typename T, typename E>
00264 inline
00265 typename ThreadSafeRegistry<KEY,T,E>::extra_type&
00266 ThreadSafeRegistry<KEY,T,E>::extra() {
00267 return extra_;
00268 }
00269
00270 template <typename KEY, typename T, typename E>
00271 inline
00272 typename ThreadSafeRegistry<KEY,T,E>::extra_type const&
00273 ThreadSafeRegistry<KEY,T,E>::extra() const {
00274 return extra_;
00275 }
00276
00277 template <typename KEY, typename T, typename E>
00278 inline
00279 typename ThreadSafeRegistry<KEY,T,E>::collection_type const&
00280 ThreadSafeRegistry<KEY,T,E>::data() const {
00281 return data_;
00282 }
00283
00284 template <typename KEY, typename T, typename E>
00285 ThreadSafeRegistry<KEY,T,E>::ThreadSafeRegistry() :
00286 data_()
00287 { }
00288
00289
00290 template <typename KEY, typename T, typename E>
00291 ThreadSafeRegistry<KEY,T,E>::~ThreadSafeRegistry()
00292 { }
00293
00294 }
00295 }
00296
00297 #endif // FWCore_Utilities_ThreadSafeRegistry_h