hash_map.hpp
Go to the documentation of this file.
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
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines


Castor
Author(s): Carpe Noctem
autogenerated on Fri Nov 8 2013 11:05:39