基于分页内存的 HASH MAP

参考VC7.1和 SGI STL 中hash_map的实现
  1. #ifndef PAGE_HASH_MAP_HPP
  2. #define PAGE_HASH_MAP_HPP
  3. #ifdef _MSC_VER
  4. # include <xutility>//iterator
  5. #else
  6. # include <iterator>
  7. #endif
  8. #include "hash.hpp"
  9. #include "allocators.hpp"
  10. namespace sm
  11. {
  12. template
  13.      <
  14.      class Key,
  15.      class Value,
  16.      class PageAlloc,
  17.      class Hash =  hash::hash_compare<Key>,
  18.      class Alloc = sm::allocator<std::pair<const Key, Value> >       
  19.      >
  20. class page_hash_map
  21. {   
  22.        page_hash_map(const page_hash_map &);       
  23.        page_hash_map & operator = (const page_hash_map &);
  24. public:
  25.     typedef page_hash_map<Key,Value,PageAlloc,Hash,Alloc> self_type;
  26.     typedef Key     key_type;
  27.     typedef Hash    key_compare;
  28.     typedef std::pair<Key,Value>  value_type;
  29.     typedef value_type &       reference;
  30.     typedef value_type const & const_reference; 
  31.     typedef ptrdiff_t difference_type;  
  32.     typedef Value     mapped_type;
  33.     typedef typename Alloc::size_type size_type;
  34.     typedef typename Alloc::offset_type offset_type;
  35.     typedef typename Alloc::byte byte;
  36.     typedef typename PageAlloc::pageid_t pageid_t;
  37.     typedef typename PageAlloc::address_t address_t;
  38.     typedef typename PageAlloc::page_traits_t page_traits_t;
  39.         
  40.     struct hash_node
  41.     {
  42.         address_t next;
  43.         value_type val;
  44.         hash_node():next(MAXPOSITION),val(value_type())
  45.         {}
  46.         hash_node(value_type const & v):next(MAXPOSITION),val(v)
  47.         {}
  48.     };
  49.     typedef typename Alloc::template rebind<hash_node>::other allocator_type;
  50.     typedef typename allocator_type::pointer pointer;
  51.         
  52.     struct const_iterator
  53.     {
  54.         typedef std::forward_iterator_tag iterator_category;
  55.         typedef difference_type distance_type;
  56.         const_iterator():ht(0),ptr(0)
  57.         {}
  58.         const_iterator(self_type * h,pointer p)
  59.         :ht(h),ptr(p)
  60.         {}
  61.         const_iterator(const_iterator const & other)
  62.         :ht(other.ht),ptr(other.ptr)
  63.         {}
  64.         const_iterator & operator = (const_iterator const & other)
  65.         {
  66.         if(this != &other)
  67.         {
  68.             this->ht = other.ht;
  69.             this->ptr = other.ptr;
  70.         }
  71.         return *this;
  72.         }
  73.         const_iterator & operator ++()
  74.         {
  75.         ptr = ht->_advance(ptr);
  76.         return *this;
  77.         }
  78.         const_iterator operator ++(int)
  79.         {
  80.         const_iterator tmp(*this);
  81.         ++*this;
  82.         return tmp;
  83.         }
  84.         const_reference operator *()const
  85.         {
  86.         return (*ptr).val;
  87.         }
  88.         bool operator == ( const_iterator const & other)
  89.         {
  90.         return ( this->ht == other.ht && this->ptr == other.ptr );
  91.         }
  92.         bool operator != ( const_iterator const & other)
  93.         {
  94.         return  !(operator ==(other) );
  95.         }   
  96.         pointer get_node()constreturn ptr;}
  97.     protected:      
  98.         self_type * ht;
  99.         pointer ptr;        
  100.     };
  101.     struct iterator : public const_iterator
  102.     {
  103.         typedef std::forward_iterator_tag iterator_category;
  104.         typedef difference_type distance_type;
  105.         iterator():const_iterator()
  106.         {}
  107.         iterator(self_type * h,pointer p)
  108.         :const_iterator(h,p)
  109.         {}      
  110.         iterator(iterator const & other):const_iterator(other)
  111.         {}
  112.         iterator & operator = (iterator const & other)
  113.         {
  114.         if(this != &other)
  115.         {
  116.             this->ht = other.ht;
  117.             this->ptr = other.ptr;
  118.         }
  119.         return *this;
  120.         }
  121.         iterator & operator ++()
  122.         {
  123.         this->ptr = this->ht->_advance(this->ptr);
  124.         return *this;
  125.         }
  126.         iterator operator ++(int)
  127.         {
  128.         iterator tmp(*this);
  129.         ++*this;
  130.         return tmp;
  131.         }
  132.         reference operator *()const
  133.         {
  134.         return (*this->ptr).val;
  135.         }
  136.         bool operator == ( iterator const & other)
  137.         {
  138.         return ( this->ht == other.ht && this->ptr == other.ptr );
  139.         }
  140.         bool operator != ( iterator const & other)
  141.         {
  142.         return  !(operator ==(other) );
  143.         }
  144.     };
  145.     typedef std::pair<iterator,bool> iterator_bool;
  146.     typedef std::pair<iterator,iterator> iterator_pair;
  147.     typedef std::pair<const_iterator,const_iterator> const_iterator_pair;
  148.     //Don't init the remembers!!!
  149.     page_hash_map()
  150.     {}
  151.     void init(pageid_t pageid,size_type n)
  152.     {   
  153.         page_ = pageid;
  154.         size_ = 0;
  155.         bucket_size_ = (size_type)hash::get_next_prime(n);
  156.         for(size_type i = 0;i < bucket_size_;++i)
  157.         buckets_[i] = MAXPOSITION;
  158.     }
  159.     static size_type get_buckets_offset(size_type n)
  160.     {
  161.         return ((hash::get_next_prime(n) -1 )* sizeof(address_t));
  162.     }
  163.     ~page_hash_map()
  164.     {
  165.     }
  166.     size_type max_size() const
  167.     {   
  168.         return bucket_size_;        
  169.     }       
  170.     size_type size() const
  171.     {       
  172.         return size_;       
  173.     }
  174.     size_type capacity()const
  175.     {
  176.         PageAlloc & pa = PageAlloc::instance();
  177.         size_type n = 0;
  178.         for(typename PageAlloc::iterator it = pa.begin(page_); it != pa.end();++it)
  179.         {
  180.         allocator_type * alloc = GETALLOCTOR(allocator_type,(*it).buf);
  181.         n += alloc->max_count();
  182.         }       
  183.         return ( n - size() );
  184.     }
  185.     size_type memory_page_count()const
  186.     {
  187.         PageAlloc & pa = PageAlloc::instance();
  188.         size_type n = 0; 
  189.         for(typename PageAlloc::iterator it = pa.begin(page_); it != pa.end();++it)
  190.         {
  191.         ++n;
  192.         }
  193.         return n;
  194.     }
  195.     double overflow()const
  196.     {
  197.         PageAlloc & pa = PageAlloc::instance();
  198.         size_type n = 0;
  199.         for(typename PageAlloc::iterator it = pa.begin(page_); it != pa.end();++it)
  200.         {
  201.         allocator_type * alloc = GETALLOCTOR(allocator_type,(*it).buf);
  202.         n += alloc->max_count();
  203.         }       
  204.         return ((double)size() / (double)n);
  205.     }
  206.     bool empty() const
  207.     {   
  208.         return (size() == 0);
  209.     }
  210.     iterator begin()
  211.     {
  212.         return  iterator(this,_first_node());
  213.     }           
  214.     iterator end()
  215.     {   
  216.         return  iterator(this,0);
  217.     }   
  218.     const_iterator begin()const
  219.     {
  220.         return  const_iterator(this,_first_node());
  221.     }           
  222.     const_iterator end()const
  223.     {   
  224.         return  const_iterator(this,0);
  225.     }   
  226.     iterator find(const key_type& key)
  227.     {   
  228.         return (lower_bound(key));
  229.     }
  230.     const_iterator find(const key_type& key)const
  231.     {   
  232.         return (lower_bound(key));
  233.     }
  234.     mapped_type & operator[](const key_type & key)
  235.     {           
  236.         iterator _Where = this->lower_bound(key);
  237.         if (_Where == this->end())
  238.         _Where = this->insert(value_type(key, mapped_type())).first;
  239.         return ((*_Where).second);
  240.     }
  241.     iterator get_iterator(size_type pos)
  242.     {   
  243.         return iterator(this,get_node(pos) );
  244.     }
  245.     const_iterator get_iterator(size_type pos)const
  246.     {   
  247.         return const_iterator(this,get_node(pos) );
  248.     }
  249.     address_t get_address(iterator it)const
  250.     {   
  251.         return address(it.get_node());
  252.     }
  253.     address_t get_address(const_iterator it)const
  254.     {   
  255.         return address(it.get_node());
  256.     }
  257.     iterator lower_bound(const key_type & key)
  258.     {           
  259.         offset_type bucket =hash_value(key);        
  260.         address_t pos = buckets_[bucket];
  261.         while(pos != MAXPOSITION )
  262.         {
  263.         pointer node = get_node(pos);
  264.         if (!comp_( get_key(*node), key))
  265.             return ( comp_(key, get_key(*node)) ? end() : iterator(this,node));
  266.         pos = node->next;
  267.         }
  268.         return end();
  269.     }
  270.     const_iterator lower_bound(const key_type & key)const
  271.     {                   
  272.         offset_type bucket =hash_value(key);        
  273.         address_t pos = buckets_[bucket];
  274.         while(pos != MAXPOSITION )
  275.         {
  276.         pointer node = get_node(pos);
  277.         if (!comp_( get_key(*node), key))
  278.             return ( comp_(key, get_key(*node)) ? end() : const_iterator(this,node));
  279.         pos = node->next;
  280.         }
  281.         return end();
  282.     }
  283.     void erase(const key_type & key)
  284.     {   
  285.                 iterator it = lower_bound(key);     
  286.         erase(it);
  287.     }
  288.     void erase(iterator first, iterator last)
  289.     {
  290.         if (first == begin() && last == end())
  291.         {
  292.         clear();
  293.         }
  294.         else
  295.         {
  296.         while (first != last)
  297.             erase(first++);
  298.         }
  299.     }
  300.     void fix()
  301.     {
  302.         offset_type n = 0;
  303.         for(iterator first = begin(); first != end();++first)++n;
  304.         size_ = n;
  305.     }
  306.     void reset(pageid_t pageid)
  307.     {
  308.              PageAlloc & pa = PageAlloc::instance();
  309.          for(typename PageAlloc::iterator it = pa.begin(pageid); it != pa.end();++it)
  310.          {
  311.          allocator_type * alloc = GETALLOCTOR(allocator_type,(*it).buf);
  312.          if( alloc->capacity() )
  313.          {
  314.                      page_ = it.get();
  315.              return;
  316.          }
  317.          }
  318.          page_ = pageid;
  319.     }
  320.     
  321.     void clear()
  322.     {                   
  323.         PageAlloc & pa = PageAlloc::instance();
  324.         for(typename PageAlloc::iterator it = pa.begin(page_); it != pa.end();++it)
  325.         {
  326.         allocator_type * alloc = GETALLOCTOR(allocator_type,(*it).buf);
  327.         alloc->reset();
  328.         }
  329.         for(size_type i = 0;i < bucket_size_;++i)
  330.         {
  331.         buckets_[i] = MAXPOSITION;
  332.         }
  333.         size_ = 0;          
  334.     } 
  335.     void erase(iterator it)
  336.     {   
  337.         offset_type bucket =hash_value( get_key(*it) );
  338.         address_t pos = buckets_[bucket];
  339.         address_t prev = pos;
  340.         while(pos != MAXPOSITION )
  341.         {
  342.         pointer node = get_node(pos);
  343.         if (!comp_( get_key(*node), get_key(*it) ))
  344.         {
  345.             if(!comp_(get_key(*it), get_key(*node )))
  346.             {
  347.             if(prev != pos )
  348.             {
  349.                 get_node(prev)->next = node->next;
  350.             }
  351.             else
  352.             {
  353.                 buckets_[bucket]=node->next;
  354.             }
  355.             --size_;
  356.             pageid_t pn = HIWORD(pos);
  357.             allocator_type & alloc = get_allocator(pn);
  358.             alloc.deallocate(node,1);
  359.             }
  360.             break;
  361.         }
  362.         prev = pos;
  363.         pos = node->next;
  364.         }
  365.     }
  366.     template<typename Handler>
  367.     bool dump_bucket(const key_type & key,Handler handler)
  368.     {       
  369.         offset_type bucket =hash_value(key);
  370.         address_t pos = buckets_[bucket];
  371.         if(pos == MAXPOSITION ) return false;
  372.         while(pos != MAXPOSITION )
  373.         {
  374.         pointer cur = get_node(pos);
  375.         handler(bucket,pos,get_key(*cur),get_value(*cur));
  376.         pos = cur->next;
  377.         }
  378.         return true;
  379.     }
  380.     iterator_bool insert(const value_type & val)
  381.     {           
  382.         offset_type bucket =hash_value( get_key(val) );
  383.         address_t & head = buckets_[bucket];
  384.         address_t pos,prev = head;
  385.         for(pos = head; pos != MAXPOSITION ;)
  386.         {
  387.         pointer node = get_node(pos);
  388.         if ( comp_( get_key(val),  get_key( *node ) ) )
  389.         {               
  390.             break;
  391.         }
  392.         else if ( comp_( get_key( *node ),  get_key(val)))
  393.         {
  394.             prev = pos;
  395.             pos = node->next;
  396.         }           
  397.         else
  398.             return (iterator_bool(iterator(this,node), false)); // already present
  399.         }
  400.         pointer newnode = new_node(val);
  401.         if(!newnode)
  402.         throw outof_memory();
  403.         ++size_;
  404.         address_t newpos = address(newnode);
  405.         newnode->next = pos;
  406.         if( prev == pos )
  407.         {               
  408.         head = newpos;
  409.         }
  410.         else
  411.         {
  412.         get_node(prev)->next = newpos;                      
  413.         }
  414.         return (iterator_bool(iterator(this,newnode), true));
  415.     }
  416. private:
  417.     static const key_type & get_key(const value_type& val)
  418.     {
  419.         return (val.first);
  420.     }   
  421.     static const key_type & get_key(const hash_node & node)
  422.     {
  423.         return get_key(node.val);
  424.     }
  425.     static const mapped_type & get_value(const hash_node & node)
  426.     {
  427.         return (node.val).second;
  428.     }
  429.     static const mapped_type & get_value(const value_type& val)
  430.     {
  431.         return (val.second);
  432.     }
  433.     
  434.     allocator_type & get_allocator(pageid_t pg)const
  435.     {
  436.         PageAlloc & pa = PageAlloc::instance();
  437.         typename PageAlloc::page * pp = pa.get_page(pg);
  438.         if(!pp)
  439.         throw page_outof_range();       
  440.         allocator_type * alloc = GETALLOCTOR(allocator_type,pp->buf);
  441.         assert(alloc);
  442.         return *alloc;
  443.     }
  444.     pointer get_node(address_t pos)const
  445.     {       
  446.         pageid_t pn = HIWORD(pos);
  447.         offset_type offset = LOWORD(pos);
  448.         allocator_type & alloc = get_allocator(pn);
  449.         return alloc.ptr(offset);
  450.     }
  451.     inline address_t address(pointer p)const
  452.     {   
  453.         PageAlloc & pa = PageAlloc::instance();
  454. #ifdef _MSC_VER
  455.         return pa.address<allocator_type>(p);
  456. #else
  457.         return pa.address((allocator_type*)0,p);        
  458. #endif
  459.     }
  460.     offset_type hash_value(key_type const & key)const
  461.     {
  462.         return (this->comp_( key ) % bucket_size_);
  463.     }
  464.     pointer new_node(const value_type& val)
  465.     {       
  466.         PageAlloc & pa = PageAlloc::instance();
  467.         pointer node = 0;
  468.         allocator_type * alloc = 0;     
  469.         typename PageAlloc::iterator it = pa.get_iterator(page_);
  470.         typename PageAlloc::iterator end = pa.end();        
  471.         for(; it != end;++it)
  472.         {
  473.         alloc = GETALLOCTOR(allocator_type,(*it).buf);
  474.         if((node=alloc->allocate() ))
  475.         {               
  476.             page_ = it.get();
  477.             construct(node,val);
  478.             return node;
  479.         }
  480.         }
  481.         it = pa.get_iterator(page_);
  482.         --it;
  483.         for(; it != end; --it)
  484.         {
  485.         alloc = GETALLOCTOR(allocator_type,(*it).buf);
  486.         if((node=alloc->allocate() ))
  487.         {                   
  488.             page_ = it.get();
  489.             construct(node,val);
  490.             return node;
  491.         }
  492.         }
  493.         alloc = new_page();
  494.         if(alloc)
  495.         {
  496.         node = alloc->allocate();               
  497.         construct(node,val);        
  498.         }
  499.         return node;
  500.     }
  501.     allocator_type * new_page()
  502.     {
  503.         assert( page_ != MAXPAGE );
  504.         PageAlloc & pa = PageAlloc::instance();
  505.         pageid_t newpage = pa.allocate();
  506.         if( MAXPAGE == newpage )
  507.         return  (allocator_type*)0;
  508.         void * pb = pa.buffer(newpage);         
  509.         SETALLOCOFFSET(pb,sizeof(offset_type));
  510.         ALLOCATE(allocator_type,alloc,pb);
  511.         alloc->open(ALLOC_SIZE(allocator_type,pb),true);
  512.         typename PageAlloc::page * np = pa.get_page(newpage);
  513.         typename PageAlloc::page * cp = pa.get_page(page_);
  514.         np->prev = cp->prev;
  515.         np->next = page_;       
  516.         if( MAXPAGE != cp->prev )
  517.         pa.get_page( cp->prev )->next = newpage;
  518.         cp->prev = newpage;
  519.         page_ = newpage;
  520.         return alloc;
  521.     }
  522.     pointer _advance(pointer p)const
  523.     {
  524.         if(p->next != MAXPOSITION)
  525.         return get_node(p->next);
  526.         offset_type bucket =hash_value( get_key(*p) );
  527.         for(size_type i = bucket + 1; i < bucket_size_;++i)
  528.         {
  529.         address_t bucket = buckets_[i];
  530.         if(bucket !=  MAXPOSITION )
  531.             return get_node(bucket);
  532.         }
  533.         return 0;
  534.     }
  535.     pointer _first_node()const
  536.     {           
  537.         for(size_type i = 0; i < bucket_size_; ++i)
  538.         {
  539.         address_t bucket = buckets_[i];
  540.         if(bucket != MAXPOSITION)
  541.             return get_node(bucket);
  542.         }
  543.         return 0;
  544.     }
  545.     pointer _next_bucket_first_node(offset_type cur)const
  546.     {           
  547.         for(size_type i = cur+1; i < bucket_size_; ++i)
  548.         {
  549.         address_t bucket = buckets_[i];
  550.         if(bucket != MAXPOSITION)
  551.             return get_node(bucket);            
  552.         }
  553.         return 0;
  554.     }   
  555. private:
  556.     pageid_t page_;
  557.     size_type size_;
  558.     size_type bucket_size_;
  559.     key_compare comp_;
  560.     address_t buckets_[1];
  561. };
  562. }; //namesapce sm
  563. #endif 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值