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