///////////////////////////////////////////////////////////////////////////// // // (C) Copyright Ion Gaztanaga 2007-2009 // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) // // See http://www.boost.org/libs/intrusive for documentation. // ///////////////////////////////////////////////////////////////////////////// #ifndef BOOST_INTRUSIVE_HASHTABLE_NODE_HPP #define BOOST_INTRUSIVE_HASHTABLE_NODE_HPP #include #include #include #include #include #include #include #include //remove-me #include #include namespace boost { namespace intrusive { namespace detail { template struct prime_list_holder { static const std::size_t prime_list[]; static const std::size_t prime_list_size; }; template const std::size_t prime_list_holder::prime_list[] = { 3ul, 7ul, 11ul, 17ul, 29ul, 53ul, 97ul, 193ul, 389ul, 769ul, 1543ul, 3079ul, 6151ul, 12289ul, 24593ul, 49157ul, 98317ul, 196613ul, 393241ul, 786433ul, 1572869ul, 3145739ul, 6291469ul, 12582917ul, 25165843ul, 50331653ul, 100663319ul, 201326611ul, 402653189ul, 805306457ul, 1610612741ul, 3221225473ul, 4294967291ul }; template const std::size_t prime_list_holder::prime_list_size = sizeof(prime_list)/sizeof(std::size_t); template struct bucket_impl : public Slist { typedef Slist slist_type; bucket_impl() {} bucket_impl(const bucket_impl &) {} ~bucket_impl() { //This bucket is still being used! BOOST_INTRUSIVE_INVARIANT_ASSERT(Slist::empty()); } bucket_impl &operator=(const bucket_impl&) { //This bucket is still in use! BOOST_INTRUSIVE_INVARIANT_ASSERT(Slist::empty()); //Slist::clear(); return *this; } }; template struct bucket_traits_impl { /// @cond typedef typename boost::pointer_to_other < typename Slist::pointer, bucket_impl >::type bucket_ptr; typedef typename Slist::size_type size_type; /// @endcond bucket_traits_impl(bucket_ptr buckets, size_type len) : buckets_(buckets), buckets_len_(len) {} bucket_ptr bucket_begin() const { return buckets_; } size_type bucket_count() const { return buckets_len_; } private: bucket_ptr buckets_; size_type buckets_len_; }; template class hashtable_iterator : public std::iterator < std::forward_iterator_tag , typename Container::value_type , typename std::iterator_traits::difference_type , typename detail::add_const_if_c ::type * , typename detail::add_const_if_c ::type & > { typedef typename Container::real_value_traits real_value_traits; typedef typename Container::siterator siterator; typedef typename Container::const_siterator const_siterator; typedef typename Container::bucket_type bucket_type; typedef typename boost::pointer_to_other < typename Container::pointer, const Container>::type const_cont_ptr; typedef typename Container::size_type size_type; static typename Container::node_ptr downcast_bucket(typename bucket_type::node_ptr p) { // This still fails in gcc < 4.4 so forget about it // using ::boost::static_pointer_cast; // return static_pointer_cast(p); return typename Container::node_ptr(&static_cast(*p)); } public: typedef typename Container::value_type value_type; typedef typename detail::add_const_if_c ::type *pointer; typedef typename detail::add_const_if_c ::type &reference; hashtable_iterator () {} explicit hashtable_iterator(siterator ptr, const Container *cont) : slist_it_ (ptr), cont_ (cont) {} hashtable_iterator(const hashtable_iterator &other) : slist_it_(other.slist_it()), cont_(other.get_container()) {} const siterator &slist_it() const { return slist_it_; } hashtable_iterator unconst() const { return hashtable_iterator(this->slist_it(), this->get_container()); } public: hashtable_iterator& operator++() { this->increment(); return *this; } hashtable_iterator operator++(int) { hashtable_iterator result (*this); this->increment(); return result; } friend bool operator== (const hashtable_iterator& i, const hashtable_iterator& i2) { return i.slist_it_ == i2.slist_it_; } friend bool operator!= (const hashtable_iterator& i, const hashtable_iterator& i2) { return !(i == i2); } reference operator*() const { return *this->operator ->(); } pointer operator->() const { return detail::boost_intrusive_get_pointer(this->get_real_value_traits()->to_value_ptr(downcast_bucket(slist_it_.pointed_node()))); } const Container *get_container() const { return detail::boost_intrusive_get_pointer(cont_); } const real_value_traits *get_real_value_traits() const { return &this->get_container()->get_real_value_traits(); } private: void increment() { const Container *cont = detail::boost_intrusive_get_pointer(cont_); bucket_type* buckets = detail::boost_intrusive_get_pointer(cont->bucket_pointer()); size_type buckets_len = cont->bucket_count(); ++slist_it_; if(buckets[0].cend().pointed_node() <= slist_it_.pointed_node() && slist_it_.pointed_node()<= buckets[buckets_len].cend().pointed_node() ){ //Now get the bucket_impl from the iterator const bucket_type &b = static_cast (bucket_type::slist_type::container_from_end_iterator(slist_it_)); //Now just calculate the index b has in the bucket array size_type n_bucket = static_cast(&b - &buckets[0]); do{ if (++n_bucket == buckets_len){ slist_it_ = (&buckets[0] + buckets_len)->end(); break; } slist_it_ = buckets[n_bucket].begin(); } while (slist_it_ == buckets[n_bucket].end()); } } siterator slist_it_; const_cont_ptr cont_; }; } //namespace detail { } //namespace intrusive { } //namespace boost { #endif