00001 #ifndef OBJMGR_MAP__HPP
00002 #define OBJMGR_MAP__HPP
00003
00004 #include <corelib/ncbistd.hpp>
00005 #include <corelib/ncbicntr.hpp>
00006 #include <map>
00007
00008 BEGIN_NCBI_SCOPE
00009
00010 #define R_WRAP(Type, Call, Declaration) \
00011 Type Declaration \
00012 { \
00013 Type ret; \
00014 RLock(); \
00015 ret = m_Container.Call; \
00016 RUnlock(); \
00017 return ret; \
00018 }
00019 #define R_WRAP_VOID(Call, Declaration) \
00020 void Declaration \
00021 { \
00022 RLock(); \
00023 m_Container.Call; \
00024 RUnlock(); \
00025 }
00026 #define W_WRAP(Type, Call, Declaration) \
00027 Type Declaration \
00028 { \
00029 Type ret; \
00030 WLock(); \
00031 ret = m_Container.Call; \
00032 WUnlock(); \
00033 return ret; \
00034 }
00035 #define W_WRAP_VOID(Call, Declaration) \
00036 void Declaration \
00037 { \
00038 WLock(); \
00039 m_Container.Call; \
00040 WUnlock(); \
00041 }
00042
00043 template<class Container>
00044 class map_checker
00045 {
00046 typedef Container container_type;
00047 typedef map_checker<Container> this_type;
00048
00049 public:
00050 typedef typename container_type::size_type size_type;
00051 typedef typename container_type::key_type key_type;
00052 typedef typename container_type::value_type value_type;
00053 typedef typename container_type::const_iterator const_iterator;
00054 typedef typename container_type::iterator iterator;
00055
00056 protected:
00057 typedef pair<const_iterator, const_iterator> const_iterator_pair;
00058 typedef pair<iterator, iterator> iterator_pair;
00059 typedef pair<iterator, bool> iterator_bool;
00060
00061 container_type m_Container;
00062 mutable CAtomicCounter_WithAutoInit m_WCounter;
00063 mutable CAtomicCounter_WithAutoInit m_RCounter;
00064
00065 public:
00066
00067 void RLock() const
00068 {
00069 if ( m_RCounter.Add(1) <= 0 || m_WCounter.Get() != 0 )
00070 abort();
00071 }
00072 void RUnlock() const
00073 {
00074 if ( m_WCounter.Get() != 0 || m_RCounter.Add(-1) < 0 )
00075 abort();
00076 }
00077 void WLock() const
00078 {
00079 if ( m_WCounter.Add(1) != 1 || m_RCounter.Get() != 0 )
00080 abort();
00081 }
00082 void WUnlock() const
00083 {
00084 if ( m_RCounter.Get() != 0 || m_WCounter.Add(-1) != 0 )
00085 abort();
00086 }
00087
00088 iterator check(iterator pos)
00089 {
00090 if ( pos != m_Container.end() ) {
00091 iterator it = m_Container.find(pos->first);
00092 if ( it != pos )
00093 abort();
00094 }
00095 return pos;
00096 }
00097
00098 map_checker()
00099 {
00100 }
00101 ~map_checker()
00102 {
00103 WLock();
00104 }
00105 map_checker(const this_type& m)
00106 {
00107 *this = m;
00108 }
00109 this_type& operator=(const this_type& m)
00110 {
00111 WLock();
00112 m.RLock();
00113 m_Container = m.m_Container;
00114 m.RUnlock();
00115 WUnlock();
00116 return *this;
00117 }
00118 void swap(this_type& m)
00119 {
00120 WLock();
00121 m.WLock();
00122 m_Container.swap(m);
00123 m.WUnlock();
00124 WUnlock();
00125 }
00126
00127 bool operator==(const this_type& m) const
00128 {
00129 bool ret;
00130 RLock();
00131 m.RLock();
00132 ret = m_Container == m.m_Container;
00133 m.RUnlock();
00134 RUnlock();
00135 return ret;
00136 }
00137 bool operator<(const this_type& m) const
00138 {
00139 bool ret;
00140 RLock();
00141 m.RLock();
00142 ret = m_Container < m.m_Container;
00143 m.RUnlock();
00144 RUnlock();
00145 return ret;
00146 }
00147
00148 R_WRAP(size_type, size(), size() const);
00149 R_WRAP(bool, empty(), empty() const);
00150
00151 R_WRAP(const_iterator, begin(), begin() const);
00152 R_WRAP(const_iterator, end(), end() const);
00153 R_WRAP(const_iterator, find(key), find(const key_type& key) const);
00154 R_WRAP(const_iterator, lower_bound(key), lower_bound(const key_type& key) const);
00155 R_WRAP(const_iterator, upper_bound(key), upper_bound(const key_type& key) const);
00156 R_WRAP(const_iterator_pair, equal_range(key), equal_range(const key_type& key) const);
00157
00158 R_WRAP(iterator, begin(), begin());
00159 R_WRAP(iterator, end(), end());
00160 R_WRAP(iterator, find(key), find(const key_type& key));
00161 R_WRAP(iterator, lower_bound(key), lower_bound(const key_type& key));
00162 R_WRAP(iterator, upper_bound(key), upper_bound(const key_type& key));
00163 R_WRAP(iterator_pair, equal_range(key), equal_range(const key_type& key));
00164
00165 W_WRAP(iterator_bool, insert(val), insert(const value_type& val));
00166 W_WRAP(iterator, insert(check(pos), val), insert(iterator pos, const value_type& val));
00167 W_WRAP_VOID(erase(check(pos)), erase(iterator pos));
00168 W_WRAP(size_type, erase(key), erase(const key_type& key));
00169 W_WRAP_VOID(clear(), clear());
00170
00171 typename container_type::mapped_type& operator[](const key_type& key)
00172 {
00173 WLock();
00174 typename container_type::mapped_type& ret = m_Container[key];
00175 WUnlock();
00176 return ret;
00177 }
00178 };
00179
00180
00181 template<class Container>
00182 class multimap_checker
00183 {
00184 typedef Container container_type;
00185 typedef multimap_checker<Container> this_type;
00186
00187 public:
00188 typedef typename container_type::size_type size_type;
00189 typedef typename container_type::key_type key_type;
00190 typedef typename container_type::value_type value_type;
00191 typedef typename container_type::const_iterator const_iterator;
00192 typedef typename container_type::iterator iterator;
00193
00194 protected:
00195 typedef pair<const_iterator, const_iterator> const_iterator_pair;
00196 typedef pair<iterator, iterator> iterator_pair;
00197 typedef pair<iterator, bool> iterator_bool;
00198
00199 container_type m_Container;
00200 mutable CAtomicCounter_WithAutoInit m_WCounter;
00201 mutable CAtomicCounter_WithAutoInit m_RCounter;
00202
00203 public:
00204
00205 void RLock() const
00206 {
00207 if ( m_RCounter.Add(1) <= 0 || m_WCounter.Get() != 0 )
00208 abort();
00209 }
00210 void RUnlock() const
00211 {
00212 if ( m_WCounter.Get() != 0 || m_RCounter.Add(-1) < 0 )
00213 abort();
00214 }
00215 void WLock() const
00216 {
00217 if ( m_WCounter.Add(1) != 1 || m_RCounter.Get() != 0 )
00218 abort();
00219 }
00220 void WUnlock() const
00221 {
00222 if ( m_RCounter.Get() != 0 || m_WCounter.Add(-1) != 0 )
00223 abort();
00224 }
00225
00226 iterator check(iterator pos)
00227 {
00228 if ( pos != m_Container.end() ) {
00229 iterator it = m_Container.find(pos->first);
00230 while ( it != m_Container.end() && it != pos && it->first == pos->first )
00231 ++it;
00232 if ( it != pos )
00233 abort();
00234 }
00235 return pos;
00236 }
00237
00238 multimap_checker()
00239 {
00240 }
00241 ~multimap_checker()
00242 {
00243 WLock();
00244 }
00245 multimap_checker(const this_type& m)
00246 {
00247 *this = m;
00248 }
00249 this_type& operator=(const this_type& m)
00250 {
00251 WLock();
00252 m.RLock();
00253 m_Container = m.m_Container;
00254 m.RUnlock();
00255 WUnlock();
00256 return *this;
00257 }
00258 void swap(this_type& m)
00259 {
00260 WLock();
00261 m.WLock();
00262 m_Container.swap(m);
00263 m.WUnlock();
00264 WUnlock();
00265 }
00266
00267 bool operator==(const this_type& m) const
00268 {
00269 bool ret;
00270 RLock();
00271 m.RLock();
00272 ret = m_Container == m.m_Container;
00273 m.RUnlock();
00274 RUnlock();
00275 return ret;
00276 }
00277 bool operator<(const this_type& m) const
00278 {
00279 bool ret;
00280 RLock();
00281 m.RLock();
00282 ret = m_Container < m.m_Container;
00283 m.RUnlock();
00284 RUnlock();
00285 return ret;
00286 }
00287
00288 R_WRAP(size_type, size(), size() const);
00289 R_WRAP(bool, empty(), empty() const);
00290
00291 R_WRAP(const_iterator, begin(), begin() const);
00292 R_WRAP(const_iterator, end(), end() const);
00293 R_WRAP(const_iterator, find(key), find(const key_type& key) const);
00294 R_WRAP(const_iterator, lower_bound(key), lower_bound(const key_type& key) const);
00295 R_WRAP(const_iterator, upper_bound(key), upper_bound(const key_type& key) const);
00296 R_WRAP(const_iterator_pair, equal_range(key), equal_range(const key_type& key) const);
00297
00298 R_WRAP(iterator, begin(), begin());
00299 R_WRAP(iterator, end(), end());
00300 R_WRAP(iterator, find(key), find(const key_type& key));
00301 R_WRAP(iterator, lower_bound(key), lower_bound(const key_type& key));
00302 R_WRAP(iterator, upper_bound(key), upper_bound(const key_type& key));
00303 R_WRAP(iterator_pair, equal_range(key), equal_range(const key_type& key));
00304
00305 W_WRAP(iterator, insert(val), insert(const value_type& val));
00306 W_WRAP(iterator, insert(check(pos), val), insert(iterator pos, const value_type& val));
00307 W_WRAP_VOID(erase(check(pos)), erase(iterator pos));
00308 W_WRAP(size_type, erase(key), erase(const key_type& key));
00309 W_WRAP_VOID(clear(), clear());
00310 };
00311
00312
00313 template<class Container>
00314 class rangemultimap_checker : public multimap_checker<Container>
00315 {
00316 typedef Container container_type;
00317 public:
00318 typedef typename container_type::key_type key_type;
00319 typedef typename container_type::range_type range_type;
00320 typedef typename container_type::iterator iterator;
00321 typedef typename container_type::const_iterator constiterator;
00322
00323 R_WRAP(iterator, begin(), begin());
00324 R_WRAP(const_iterator, begin(), begin() const);
00325 R_WRAP(iterator, begin(range), begin(const range_type& range));
00326 R_WRAP(const_iterator, begin(range), begin(const range_type& range) const);
00327 };
00328
00329
00330
00331 #undef R_WRAP
00332 #undef R_WRAP_VOID
00333 #undef W_WRAP
00334 #undef W_WRAP_VOID
00335
00336 template<typename Key, typename T, typename Compare = less<Key> >
00337 class map : public map_checker< std::map<Key, T, Compare> >
00338 {
00339 };
00340
00341
00342 template<typename Key, typename T, typename Compare = less<Key> >
00343 class multimap : public multimap_checker< std::multimap<Key, T, Compare> >
00344 {
00345 };
00346
00347
00348 END_NCBI_SCOPE
00349
00350 #endif//OBJMGR_MAP__HPP
00351
00352