$search
00001 // 00002 // hash_map.hpp 00003 // ~~~~~~~~~~~~ 00004 // 00005 // Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) 00006 // 00007 // Distributed under the Boost Software License, Version 1.0. (See accompanying 00008 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 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 // Note: assumes K and V are POD types. 00047 template <typename K, typename V> 00048 class hash_map 00049 : private noncopyable 00050 { 00051 public: 00052 // The type of a value in the map. 00053 typedef std::pair<K, V> value_type; 00054 00055 // The type of a non-const iterator over the hash map. 00056 typedef typename std::list<value_type>::iterator iterator; 00057 00058 // The type of a const iterator over the hash map. 00059 typedef typename std::list<value_type>::const_iterator const_iterator; 00060 00061 // Constructor. 00062 hash_map() 00063 { 00064 // Initialise all buckets to empty. 00065 for (size_t i = 0; i < num_buckets; ++i) 00066 buckets_[i].first = buckets_[i].last = values_.end(); 00067 } 00068 00069 // Get an iterator for the beginning of the map. 00070 iterator begin() 00071 { 00072 return values_.begin(); 00073 } 00074 00075 // Get an iterator for the beginning of the map. 00076 const_iterator begin() const 00077 { 00078 return values_.begin(); 00079 } 00080 00081 // Get an iterator for the end of the map. 00082 iterator end() 00083 { 00084 return values_.end(); 00085 } 00086 00087 // Get an iterator for the end of the map. 00088 const_iterator end() const 00089 { 00090 return values_.end(); 00091 } 00092 00093 // Check whether the map is empty. 00094 bool empty() const 00095 { 00096 return values_.empty(); 00097 } 00098 00099 // Find an entry in the map. 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 // Find an entry in the map. 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 // Insert a new entry into the map. 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 // Erase an entry from the map. 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 // Remove all entries from the map. 00177 void clear() 00178 { 00179 // Clear the values. 00180 values_.clear(); 00181 00182 // Initialise all buckets to empty. 00183 for (size_t i = 0; i < num_buckets; ++i) 00184 buckets_[i].first = buckets_[i].last = values_.end(); 00185 } 00186 00187 private: 00188 // Insert an element into the values list by splicing from the spares list, 00189 // if a spare is available, and otherwise by inserting a new element. 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 // Erase an element from the values list by splicing it to the spares list. 00205 void values_erase(iterator it) 00206 { 00207 *it = value_type(); 00208 spares_.splice(spares_.begin(), values_, it); 00209 } 00210 00211 // The list of all values in the hash map. 00212 std::list<value_type> values_; 00213 00214 // The list of spare nodes waiting to be recycled. Assumes that POD types only 00215 // are stored in the hash map. 00216 std::list<value_type> spares_; 00217 00218 // The type for a bucket in the hash table. 00219 struct bucket_type 00220 { 00221 iterator first; 00222 iterator last; 00223 }; 00224 00225 // The number of buckets in the hash. 00226 enum { num_buckets = 1021 }; 00227 00228 // The buckets in the hash. 00229 bucket_type buckets_[num_buckets]; 00230 }; 00231 00232 } // namespace detail 00233 } // namespace asio 00234 00235 #include "asio/detail/pop_options.hpp" 00236 00237 #endif // ASIO_DETAIL_HASH_MAP_HPP