00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054 #ifndef W_HASH_H
00055 #define W_HASH_H
00056
00057 #include "w_defines.h"
00058
00059
00060
00061
00062
00063
00064 #include <w_base.h>
00065 #include <w_list.h>
00066
00067 template <class T, class LOCK, class K> class w_hash_t;
00068 template <class T, class LOCK, class K> class w_hash_i;
00069
00070 BIND_FRIEND_OPERATOR_PART_1B(T,LOCK,K,w_hash_t<T,LOCK,K>)
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093 template <class T, class LOCK, class K>
00094 class w_hash_t : public w_base_t {
00095 public:
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113 NORET w_hash_t(
00114 uint4_t sz,
00115 uint4_t key_offset,
00116 uint4_t link_offset,
00117 const LOCK * lock);
00118 NORET ~w_hash_t();
00119
00120 private:
00121 uint4_t bucket_for(K const &k) const;
00122 uint4_t bucket_for(T const *t) const;
00123
00124 public:
00125
00126 w_hash_t& push(T* t);
00127
00128 w_hash_t& append(T* t);
00129
00130 T* lookup(const K& k) const;
00131
00132 bool member(T const *t) const;
00133
00134 T* remove(const K& k);
00135
00136 void remove(T* t);
00137
00138 uint4_t num_members() const { return _cnt; }
00139
00140
00141 friend ostream& operator<<
00142 BIND_FRIEND_OPERATOR_PART_2B(T,LOCK,K) (
00143 ostream& o,
00144 const w_hash_t<T,LOCK,K>& obj);
00145
00146
00147 private:
00148 friend class w_hash_i<T,LOCK,K>;
00149 uint4_t _top;
00150 uint4_t _mask;
00151 uint4_t _cnt;
00152 uint4_t _key_offset;
00153 uint4_t _link_offset;
00154 w_list_t<T, LOCK>* _tab;
00155
00156 const K& _keyof(const T& t) const {
00157 return * (K*) (((const char*)&t) + _key_offset);
00158 }
00159 w_link_t& _linkof(T& t) const {
00160 return * (w_link_t*) (((char*)&t) + _link_offset);
00161 }
00162
00163
00164 NORET w_hash_t(const w_hash_t&)
00165 ;
00166 w_hash_t& operator=(const w_hash_t&)
00167 ;
00168 };
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189 #define W_HASH_ARG(class,key,link) W_KEYED_ARG(class, key, link)
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212 template <class T, class LOCK, class K>
00213 class w_hash_i : public w_base_t {
00214 public:
00215 NORET w_hash_i(const w_hash_t<T,LOCK, K>& t) : _bkt(uint4_max),
00216 _htab(t) {};
00217
00218 NORET ~w_hash_i() {};
00219
00220 T* next();
00221 T* curr() { return _iter.curr(); }
00222
00223 private:
00224 uint4_t _bkt;
00225 w_list_i<T,LOCK> _iter;
00226 const w_hash_t<T,LOCK, K>& _htab;
00227
00228 NORET w_hash_i(w_hash_i&);
00229
00230 w_hash_i& operator=(w_hash_i&)
00231 ;
00232 };
00233
00234
00235 template <class T, class LOCK, class K>
00236 ostream& operator<<(
00237 ostream& o,
00238 const w_hash_t<T,LOCK, K>& h)
00239 {
00240 for (int i = 0; i < h._top; i++) {
00241 o << '[' << i << "] ";
00242 w_list_i<T,LOCK> iter(h._tab[i]);
00243 while (iter.next()) {
00244 o << h._keyof(*iter.curr()) << " ";
00245 }
00246 o << endl;
00247 }
00248 return o;
00249 }
00250
00251
00252 template <class T, class LOCK, class K>
00253 NORET
00254 w_hash_t<T,LOCK, K>::w_hash_t(
00255 w_base_t::uint4_t sz,
00256 w_base_t::uint4_t key_offset,
00257 w_base_t::uint4_t link_offset,
00258 const LOCK *)
00259 : _top(0), _cnt(0), _key_offset(key_offset),
00260 _link_offset(link_offset), _tab(0)
00261 {
00262 for (_top = 1; _top < sz; _top <<= 1) ;
00263 _mask = _top - 1;
00264
00265 w_assert1(!_tab);
00266 _tab = new w_list_t<T,LOCK>[_top];
00267 w_assert1(_tab);
00268 for (unsigned i = 0; i < _top; i++) {
00269 _tab[i].set_offset(_link_offset);
00270 }
00271 }
00272
00273 template <class T, class LOCK, class K>
00274 NORET
00275 w_hash_t<T,LOCK, K>::~w_hash_t()
00276 {
00277 w_assert1(_cnt == 0);
00278 delete[] _tab;
00279 }
00280
00281
00282 template<class T, class LOCK, class K>
00283 w_base_t::uint4_t w_hash_t<T,LOCK, K>::bucket_for(T const* t) const {
00284 return bucket_for(_keyof(*t));
00285 }
00286
00287 template<class T, class LOCK, class K>
00288 w_base_t::uint4_t w_hash_t<T,LOCK, K>::bucket_for(K const &k) const {
00289 return k.hash() & _mask;
00290 }
00291
00292 template <class T, class LOCK, class K>
00293 w_hash_t<T,LOCK, K>&
00294 w_hash_t<T,LOCK, K>::push(T* t)
00295 {
00296 _tab[bucket_for(t)].push(t);
00297 ++_cnt;
00298 w_assert1(int(_cnt) > 0);
00299 return *this;
00300 }
00301
00302 template <class T, class LOCK, class K>
00303 w_hash_t<T,LOCK, K>& w_hash_t<T,LOCK, K>::append(T* t)
00304 {
00305 _tab[bucket_for(t)].append(t);
00306 ++_cnt;
00307 w_assert1(int(_cnt) > 0);
00308 return *this;
00309 }
00310
00311 template <class T, class LOCK, class K>
00312 T*
00313 w_hash_t<T,LOCK, K>::lookup(const K& k) const
00314 {
00315 w_list_t<T,LOCK>& list = _tab[bucket_for(k)];
00316 w_list_i<T,LOCK> i( list );
00317 register T* t;
00318 int4_t count;
00319 for (count = 0; (t = i.next()) && ! (_keyof(*t) == k); ++count) ;
00320
00321
00322
00323
00324 if (0 && t && count) {
00325 w_link_t& link = _linkof(*t);
00326 link.detach();
00327 list.push(t);
00328 }
00329
00330 return t;
00331 }
00332 template <class T, class LOCK, class K>
00333 bool
00334 w_hash_t<T,LOCK, K>::member(T const* t) const
00335 {
00336 w_list_base_t* list = &_tab[bucket_for(t)];
00337 return t->link.member_of() == list;
00338 }
00339
00340 template <class T, class LOCK, class K>
00341 T*
00342 w_hash_t<T,LOCK, K>::remove(const K& k)
00343 {
00344 w_list_i<T,LOCK> i(_tab[bucket_for(k)]);
00345 while (i.next() && ! (_keyof(*i.curr()) == k)) ;
00346
00347 T *tmp = i.curr();
00348 if (tmp) {
00349 --_cnt;
00350 w_assert1(int(_cnt) >= 0);
00351 _linkof(*tmp).detach();
00352 }
00353 return tmp;
00354 }
00355
00356 template <class T, class LOCK, class K>
00357 void
00358 w_hash_t<T,LOCK, K>::remove(T* t)
00359 {
00360 w_assert1(_linkof(*t).member_of() ==
00361 &_tab[bucket_for(t)]);
00362 _linkof(*t).detach();
00363 --_cnt;
00364 w_assert1(int(_cnt) >= 0);
00365 }
00366
00367 template <class T, class LOCK, class K>
00368 T* w_hash_i<T,LOCK, K>::next()
00369 {
00370 if (_bkt == uint4_max) {
00371 _bkt = 0;
00372 _iter.reset(_htab._tab[_bkt++]);
00373 }
00374
00375 if (! _iter.next()) {
00376 while (_bkt < _htab._top) {
00377
00378 _iter.reset( _htab._tab[ _bkt++ ] );
00379 if (_iter.next()) break;
00380 }
00381 }
00382 return _iter.curr();
00383 }
00384
00385
00386
00387 #endif