Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #ifndef ASIO_DETAIL_HASH_MAP_HPP
00012 #define ASIO_DETAIL_HASH_MAP_HPP
00013
00014 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
00015 # pragma once
00016 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
00017
00018 #include "asio/detail/push_options.hpp"
00019
00020 #include "asio/detail/push_options.hpp"
00021 #include <cassert>
00022 #include <list>
00023 #include <utility>
00024 #include <boost/functional/hash.hpp>
00025 #include "asio/detail/pop_options.hpp"
00026
00027 #include "asio/detail/noncopyable.hpp"
00028 #include "asio/detail/socket_types.hpp"
00029
00030 namespace asio {
00031 namespace detail {
00032
00033 template <typename T>
00034 inline std::size_t calculate_hash_value(const T& t)
00035 {
00036 return boost::hash_value(t);
00037 }
00038
00039 #if defined(_WIN64)
00040 inline std::size_t calculate_hash_value(SOCKET s)
00041 {
00042 return static_cast<std::size_t>(s);
00043 }
00044 #endif // defined(_WIN64)
00045
00046
00047 template <typename K, typename V>
00048 class hash_map
00049 : private noncopyable
00050 {
00051 public:
00052
00053 typedef std::pair<K, V> value_type;
00054
00055
00056 typedef typename std::list<value_type>::iterator iterator;
00057
00058
00059 typedef typename std::list<value_type>::const_iterator const_iterator;
00060
00061
00062 hash_map()
00063 {
00064
00065 for (size_t i = 0; i < num_buckets; ++i)
00066 buckets_[i].first = buckets_[i].last = values_.end();
00067 }
00068
00069
00070 iterator begin()
00071 {
00072 return values_.begin();
00073 }
00074
00075
00076 const_iterator begin() const
00077 {
00078 return values_.begin();
00079 }
00080
00081
00082 iterator end()
00083 {
00084 return values_.end();
00085 }
00086
00087
00088 const_iterator end() const
00089 {
00090 return values_.end();
00091 }
00092
00093
00094 bool empty() const
00095 {
00096 return values_.empty();
00097 }
00098
00099
00100 iterator find(const K& k)
00101 {
00102 size_t bucket = calculate_hash_value(k) % num_buckets;
00103 iterator it = buckets_[bucket].first;
00104 if (it == values_.end())
00105 return values_.end();
00106 iterator end = buckets_[bucket].last;
00107 ++end;
00108 while (it != end)
00109 {
00110 if (it->first == k)
00111 return it;
00112 ++it;
00113 }
00114 return values_.end();
00115 }
00116
00117
00118 const_iterator find(const K& k) const
00119 {
00120 size_t bucket = calculate_hash_value(k) % num_buckets;
00121 const_iterator it = buckets_[bucket].first;
00122 if (it == values_.end())
00123 return it;
00124 const_iterator end = buckets_[bucket].last;
00125 ++end;
00126 while (it != end)
00127 {
00128 if (it->first == k)
00129 return it;
00130 ++it;
00131 }
00132 return values_.end();
00133 }
00134
00135
00136 std::pair<iterator, bool> insert(const value_type& v)
00137 {
00138 size_t bucket = calculate_hash_value(v.first) % num_buckets;
00139 iterator it = buckets_[bucket].first;
00140 if (it == values_.end())
00141 {
00142 buckets_[bucket].first = buckets_[bucket].last =
00143 values_insert(values_.end(), v);
00144 return std::pair<iterator, bool>(buckets_[bucket].last, true);
00145 }
00146 iterator end = buckets_[bucket].last;
00147 ++end;
00148 while (it != end)
00149 {
00150 if (it->first == v.first)
00151 return std::pair<iterator, bool>(it, false);
00152 ++it;
00153 }
00154 buckets_[bucket].last = values_insert(end, v);
00155 return std::pair<iterator, bool>(buckets_[bucket].last, true);
00156 }
00157
00158
00159 void erase(iterator it)
00160 {
00161 assert(it != values_.end());
00162
00163 size_t bucket = calculate_hash_value(it->first) % num_buckets;
00164 bool is_first = (it == buckets_[bucket].first);
00165 bool is_last = (it == buckets_[bucket].last);
00166 if (is_first && is_last)
00167 buckets_[bucket].first = buckets_[bucket].last = values_.end();
00168 else if (is_first)
00169 ++buckets_[bucket].first;
00170 else if (is_last)
00171 --buckets_[bucket].last;
00172
00173 values_erase(it);
00174 }
00175
00176
00177 void clear()
00178 {
00179
00180 values_.clear();
00181
00182
00183 for (size_t i = 0; i < num_buckets; ++i)
00184 buckets_[i].first = buckets_[i].last = values_.end();
00185 }
00186
00187 private:
00188
00189
00190 iterator values_insert(iterator it, const value_type& v)
00191 {
00192 if (spares_.empty())
00193 {
00194 return values_.insert(it, v);
00195 }
00196 else
00197 {
00198 spares_.front() = v;
00199 values_.splice(it, spares_, spares_.begin());
00200 return --it;
00201 }
00202 }
00203
00204
00205 void values_erase(iterator it)
00206 {
00207 *it = value_type();
00208 spares_.splice(spares_.begin(), values_, it);
00209 }
00210
00211
00212 std::list<value_type> values_;
00213
00214
00215
00216 std::list<value_type> spares_;
00217
00218
00219 struct bucket_type
00220 {
00221 iterator first;
00222 iterator last;
00223 };
00224
00225
00226 enum { num_buckets = 1021 };
00227
00228
00229 bucket_type buckets_[num_buckets];
00230 };
00231
00232 }
00233 }
00234
00235 #include "asio/detail/pop_options.hpp"
00236
00237 #endif // ASIO_DETAIL_HASH_MAP_HPP