基于分页的内存分配器

   工作中要用到一个基于共享内存的HASH TABLE,也就是数据和HASH TABLE自身的成员变量都要放到共享内存上,自然内存分配也要自己写。
   先贴出代码,感兴趣的我们在讨论:)
  1. #ifndef _ALLOCATORS_HPP_
  2. #define _ALLOCATORS_HPP_
  3. #include <cassert>
  4. #define MAXPAGE  ((pageid_t)0xFFFFFFFF)
  5. #define PAGESIZE (1024 * 16)
  6. #if defined(__LP64__) || defined(__64BIT__) || defined(_LP64) || defined (_AMD64__)|| defined(__IA64__)
  7. # define MAXPOSITION ((size_t)0xFFFFFFFFFFFFFFFF)
  8. # define SHIFTBITS   32
  9. typedef unsigned int WORD;
  10. # define MASKBITS   0xFFFFFFFF
  11. #else
  12. # define MAXPOSITION ((size_t)0xFFFFFFFF)
  13. # define SHIFTBITS   16
  14. typedef unsigned short WORD;
  15. # define MASKBITS   0xFFFF
  16. #endif
  17. #define ALLOC_OFFSET(p) *((offset_type*)p)
  18. #define ALLOCATE(A,alloc,p)  A * alloc = (A*)((byte*)p + ALLOC_OFFSET(p));construct(alloc)
  19. #define GETALLOCTOR(A,p)  (A*)( (byte*)p + ALLOC_OFFSET(p))
  20. #define SETALLOCOFFSET(p,offset) *((offset_type*)p)=(offset)
  21. #define ALLOC_SIZE(A,p) (PAGESIZE - ALLOC_OFFSET(p)-sizeof(A))
  22. #define MAKEULONG(l,h)  ((size_t)(((WORD)((size_t)(l) & MASKBITS)) | ((size_t)((WORD)((size_t)(h) & MASKBITS))) << SHIFTBITS))
  23. #define HIWORD(a)   ((WORD)((a >> SHIFTBITS ) & MASKBITS))
  24. #define LOWORD(a)   ((WORD)(a & MASKBITS))
  25. namespace sm
  26. {
  27. struct outof_memory{};
  28. struct page_outof_range{};
  29. template<typename T>
  30. void construct(T * ptr)
  31. {
  32.     ::new (ptr)T();
  33. }
  34. template<typename T,typename V>
  35. void construct(T * ptr, const V & val)
  36. {
  37.     ::new (ptr)T(val);
  38. }           
  39. template<typename T,typename A1,typename A2>
  40. void construct(T * ptr, const A1 & a1,const A2 & a2)
  41. {
  42.     ::new (ptr)T(a1,a2);
  43. }       
  44. template<typename T>
  45. void destroy(T * ptr)
  46. {
  47.     ptr->~T();
  48. }
  49. template<int bits> struct page_traits;
  50. template<>
  51. struct page_traits<8>
  52. {
  53.     typedef size_t        size_type;
  54.     typedef unsigned int  offset_type;
  55.     typedef unsigned int  pageid_type;
  56.     typedef size_t        address_type;
  57.     typedef unsigned char byte;
  58.     enum{ BUFSIZE = PAGESIZE - sizeof(pageid_type) * 2 };
  59. };
  60. template<>
  61. struct page_traits<4>
  62. {
  63.     typedef size_t   size_type;
  64.     typedef unsigned int    offset_type;
  65.     typedef unsigned int    pageid_type;
  66.     typedef size_t   address_type;
  67.     typedef unsigned char   byte;
  68.     enum{ BUFSIZE = PAGESIZE - sizeof(pageid_type) * 2 };
  69. };
  70. template<class T>
  71. class allocator
  72. {       
  73. public:
  74.     typedef page_traits<sizeof(size_t)>           page_traits_t;
  75.     typedef typename page_traits_t::size_type   size_type;
  76.     typedef typename page_traits_t::offset_type offset_type;    
  77.     typedef typename page_traits_t::byte        byte;
  78.     typedef typename page_traits_t::address_type  address_type;
  79.     typedef T value_type;
  80.     typedef T * pointer;        
  81.     struct memory_thunk
  82.     {
  83.         union
  84.         {
  85.            byte data[sizeof(value_type)];
  86.            offset_type offset;
  87.         };
  88.     };
  89. public:
  90.     template<class _Other>
  91.     struct rebind
  92.     {   
  93.         typedef allocator<_Other> other;
  94.     };  
  95.     allocator()
  96.     {}
  97.     static size_type thunks_size(size_type n)
  98.     {
  99.         return (sizeof(memory_thunk) * n);
  100.     }
  101.     void open(size_type sz,bool init)
  102.     {           
  103.         if( init )
  104.         {
  105.             cur_ = offset_type(0);
  106.             last_ = (offset_type)( sz / sizeof(memory_thunk) ) - 1;
  107.             tidy();
  108.         }
  109.     }
  110.     inline bool exists(pointer p)const
  111.     {
  112.         if(!p)return false;
  113.         memory_thunk * c = reinterpret_cast<memory_thunk*>(p);      
  114.         return (c < pool_ + last_ && c >= pool_);
  115.     }   
  116.     inline pointer allocate()
  117.     {           
  118.         if(cur_ < last_ )
  119.         {
  120.             memory_thunk * thunk = pool_+ cur_;
  121.             cur_ = thunk->offset;
  122.             return reinterpret_cast<pointer>( thunk );
  123.         }
  124.         return 0;
  125.     }
  126.     inline void deallocate(pointer p,size_type)
  127.     {       
  128.         if(p && exists(p) )
  129.         {
  130.             memory_thunk * thunk = reinterpret_cast<memory_thunk*>( p );
  131.             size_type pos = thunk - pool_;
  132.             thunk->offset = cur_;
  133.             cur_ = pos;
  134.         }
  135.     }   
  136.     inline offset_type address(pointer p)const
  137.     {
  138.         assert( p != 0 );
  139.             assert( p >= (pointer)pool_ );
  140.         assert( last_ > 0 );
  141.             assert( (memory_thunk*)p < (pool_ + last_) );   
  142.         offset_type ret = offset_type(reinterpret_cast<memory_thunk*>(p)-pool_);
  143.         assert( ret >=0 && ret < last_ );
  144.         return ret;
  145.     }
  146.     inline pointer ptr(offset_type pos)const
  147.     {
  148.         assert( pos >=0 && pos < last_ );
  149.         return reinterpret_cast<pointer>(const_cast<memory_thunk*>(pool_+pos));
  150.     }   
  151.     inline void reset()
  152.     {
  153.         cur_ = 0;
  154.         tidy();
  155.     }   
  156.     size_type max_count()const
  157.     {
  158.         return last_;
  159.     }
  160.     bool empty()
  161.     {
  162.         return (capacity() == (size_t)last_);
  163.     }
  164.     size_t capacity()
  165.     {
  166.         offset_type n=0;
  167.         offset_type pos = cur_;
  168.         while(pos < last_ )
  169.         {
  170.         ++n;
  171.         memory_thunk * thunk = pool_+ pos;
  172.         pos = thunk->offset;
  173.         }
  174.             return (size_t)n;
  175.     }
  176. private:
  177.     void tidy()
  178.     {       
  179.         assert(last_ > 0 );     
  180.         for(offset_type i = 0;i < last_;++i)
  181.         {
  182.             pool_[i].offset=i+1;    
  183.         }
  184.     }
  185. private:    
  186.     offset_type cur_;
  187.     offset_type last_;
  188.     memory_thunk pool_[0];
  189. };
  190. template<class _Ty,class _Other>
  191. inline  bool operator==(const allocator<_Ty>&, const allocator<_Other>&) throw()
  192. {   
  193.     return (true);
  194. }
  195. template<class _Ty,class _Other>
  196. inline  bool operator!=(const allocator<_Ty>&, const allocator<_Other>&) throw()
  197. {   
  198.     return (false);
  199. }
  200. //
  201. //page_allocator
  202. ///
  203. template<typename L>
  204. class page_allocator
  205. {   
  206. public:
  207.     typedef page_traits<sizeof(size_t)>   page_traits_t;
  208.     typedef page_traits_t::size_type    size_type;
  209.     typedef page_traits_t::offset_type  offset_type;
  210.     typedef page_traits_t::pageid_type  pageid_t;
  211.     typedef page_traits_t::address_type address_t;
  212.     typedef page_traits_t::byte         byte;
  213.     enum{ BUFSIZE = page_traits_t::BUFSIZE };
  214.     
  215.     struct page
  216.     {       
  217.         pageid_t prev;
  218.         pageid_t next;      
  219.         byte buf[BUFSIZE];
  220.     };
  221.     struct auto_page
  222.     {
  223.         pageid_t pageid;
  224.         auto_page(pageid_t pageid):pageid(pageid)
  225.         {}
  226.         ~auto_page()
  227.         {
  228.         if(pageid != MAXPAGE)
  229.         {
  230.             page_allocator<L>::instance().deallocate(pageid);
  231.             pageid = MAXPAGE;
  232.         }
  233.         }
  234.         pageid_t release()
  235.         {
  236.         pageid_t ret = pageid;
  237.         pageid = MAXPAGE;
  238.         return ret;
  239.         }
  240.     };
  241. private:
  242.     page_allocator()
  243.         :lock(),buf_(0),cursor_(0),pagepool_(0),size_(0),lastpage_(0)
  244.         {}
  245.     page_allocator(page_allocator const&);
  246.     page_allocator & operator = (page_allocator const&);
  247. public:
  248.     struct iterator
  249.     {
  250.         page_allocator * pa_;
  251.         pageid_t page_;
  252.         iterator():pa_(0),page_(MAXPAGE){}
  253.         iterator(page_allocator * a,pageid_t p):pa_(a),page_(p){}
  254.         iterator(iterator const & other):pa_(other.pa_),page_(other.page_){}
  255.         iterator & operator = ( iterator const & other)
  256.         {
  257.             pa_ = other.pa_;
  258.             page_ = other.page_;
  259.             return *this;
  260.         }
  261.         iterator & operator ++()
  262.         {
  263.              page_ = pa_->get_page(page_)->next;             
  264.              return *this;
  265.         }
  266.         iterator operator ++(int)
  267.         {
  268.             iterator tmp(*this);
  269.             ++*this;
  270.             return tmp;
  271.         }
  272.         iterator & operator --()
  273.         {
  274.              page_ = pa_->get_page(page_)->prev;             
  275.              return *this;
  276.         }
  277.         iterator operator --(int)
  278.         {
  279.             iterator tmp(*this);
  280.             --*this;
  281.             return tmp;
  282.         }
  283.         page & operator*()
  284.         {
  285.             assert( pa_ !=0 );
  286.             assert( page_ != MAXPAGE);
  287.             page * p = pa_->get_page(page_);
  288.             return *p;
  289.         }
  290.         page const & operator *()const
  291.         {
  292.             assert( pa_ !=0 );
  293.             assert( page_ != MAXPAGE);
  294.             page * p = pa_->get_page(page_);
  295.             return *p;
  296.         }
  297.         pageid_t get()constreturn page_;}
  298.         bool operator == ( iterator const & other)
  299.         {
  300.             return (pa_ == other.pa_ && page_ == other.page_);
  301.         }
  302.         bool operator != ( iterator const & other)
  303.         {
  304.             return  !(operator ==(other) );
  305.         }
  306.     };
  307.     iterator get_iterator(pageid_t pn)
  308.     {
  309.         return iterator(this,pn);
  310.     }   
  311.     iterator end()
  312.     {
  313.         return  iterator(this,MAXPAGE);
  314.     }
  315.     iterator begin(pageid_t pn)
  316.     {   
  317.         pageid_t tmp = MAXPAGE;
  318.         while(pn != MAXPAGE )
  319.         {
  320.         tmp = pn;
  321.         pn = get_page(tmp)->prev;          
  322.         }
  323.         return  iterator(this,tmp);
  324.     }
  325.     iterator rbein(pageid_t pn)
  326.     {
  327.         pageid_t tmp = MAXPAGE;
  328.         while(pn != MAXPAGE )
  329.         {
  330.         tmp = pn;
  331.         pn = get_page(tmp)->next;          
  332.         }
  333.         return  iterator(this,tmp);
  334.     }
  335.     size_t deallocate_page_list(pageid_t pageid)
  336.     {
  337.         iterator it = begin(pageid);
  338.         if(it == end() ) return 0;
  339.         pageid = it.get();
  340.         size_t ret  = 0;
  341.         while(pageid != MAXPAGE )
  342.         {
  343.         pageid_t tmp = pageid;
  344.         page * p = get_page(tmp);
  345.         pageid = p->next;
  346.         deallocate( tmp );
  347.         ++ret;
  348.         }
  349.         return ret;
  350.     }
  351.     bool open(byte* buf,size_t sz)
  352.     {
  353.         buf_ = buf;
  354.         size_ = sz;
  355.         if(!buf ) return false;     
  356.         if( size_ < ( sizeof(pageid_t) + PAGESIZE ) )
  357.         return false;
  358.         pagepool_ = reinterpret_cast<page*>(buf_ + sizeof(pageid_t));
  359.         lastpage_ = (pageid_t)(size_- sizeof(pageid_t)) / PAGESIZE;
  360.         cursor_ = (pageid_t*)(buf_);        
  361.         return true;
  362.     }
  363.     bool create(byte* buf,size_t sz)
  364.     {       
  365.         buf_ = buf;
  366.         size_ = sz;
  367.         if(!buf ) return false;
  368.         if( size_ < ( sizeof(pageid_t)+ PAGESIZE ) )
  369.         return false;
  370.         pagepool_ = reinterpret_cast<page*>(buf_ + sizeof(pageid_t));
  371.         lastpage_ = (pageid_t)(size_ - sizeof(pageid_t)) / PAGESIZE;
  372.         cursor_ = (pageid_t*)(buf_);        
  373.         *cursor_ = 0;
  374.         tidy();
  375.         return true;
  376.     }   
  377.     pageid_t allocate()
  378.     {   
  379.         typename L::scoped_lock guard(lock);
  380.         pageid_t ret = MAXPAGE;
  381.         assert(cursor_ );
  382.         assert(lastpage_ > 0 );
  383.         assert( size_ > PAGESIZE );
  384.         if( MAXPAGE != *cursor_ )
  385.         {                
  386.         ret = *cursor_;
  387.         assert( (pagepool_ + *cursor_)->prev ==MAXPAGE );
  388.         pageid_t next = (pagepool_ + *cursor_)->next;
  389.         if(next != MAXPAGE )
  390.         {
  391.             *cursor_ = next;
  392.             (pagepool_ + next)->prev = MAXPAGE;
  393.         }
  394.         else
  395.         {
  396.             *cursor_ = MAXPAGE;
  397.         }
  398.         (pagepool_+ ret)->next = MAXPAGE;
  399.         assert( (pagepool_+ ret)->prev == MAXPAGE );
  400.         }
  401.         return ret;
  402.     }
  403.     void deallocate(pageid_t pageid)
  404.     {           
  405.         typename L::scoped_lock guard(lock);
  406.         assert(cursor_ );
  407.         assert(lastpage_ > 0 );
  408.         assert( size_ > PAGESIZE );
  409.         if(inrange(pageid) )
  410.         {       
  411.                 (pagepool_+ pageid)->prev = MAXPAGE;
  412.         (pagepool_+ pageid)->next = *cursor_;
  413.         if( *cursor_ != MAXPAGE)
  414.         {
  415.             assert( (pagepool_+ *cursor_)->prev == MAXPAGE );
  416.             (pagepool_+ *cursor_)->prev = pageid;
  417.         }
  418.         *cursor_ = pageid;
  419.         }       
  420.     }
  421.     template<typename A>
  422.         int gc(A*,pageid_t pageid)
  423.     {
  424.         int res = 0;
  425.         //next
  426.         assert( inrange(pageid) );
  427.         pageid_t next = (pagepool_+ pageid)->next;
  428.         while(next != MAXPAGE )
  429.         {
  430.         assert( inrange(next) );
  431.         pageid_t n = (pagepool_+ next)->next;
  432.         A * alloc =GETALLOCTOR(A,(pagepool_ + next)->buf);
  433.         if( alloc->empty() )
  434.         {
  435.             pageid_t p = (pagepool_+ next)->prev;
  436.             (pagepool_+ p)->next = n;
  437.             if(n != MAXPAGE )
  438.             {
  439.             (pagepool_+ n)->prev = p;
  440.             }
  441.             (pagepool_+ next)->next = MAXPAGE;
  442.             (pagepool_+ next)->prev = MAXPAGE;
  443.             deallocate(next);
  444.             ++res;
  445.             next = n;
  446.         }
  447.         else
  448.         {
  449.             next = n;
  450.         }
  451.         }
  452.         //prev
  453.         pageid_t prev = (pagepool_+ pageid)->prev;
  454.         while(prev != MAXPAGE )
  455.         {
  456.         assert( inrange(prev) );
  457.         pageid_t p = (pagepool_+ prev)->prev;
  458.         A * alloc =GETALLOCTOR(A,(pagepool_ + prev)->buf);
  459.         if( alloc->empty() )
  460.         {
  461.             pageid_t n = (pagepool_+ prev)->next;
  462.             (pagepool_+ n)->prev = p;
  463.             if(p != MAXPAGE )
  464.             {
  465.             (pagepool_+ p)->next = n;
  466.             }
  467.             ++res;
  468.             (pagepool_+ prev)->next = MAXPAGE;
  469.                     (pagepool_+ prev)->prev = MAXPAGE;
  470.             deallocate(prev);
  471.             prev = p;
  472.         }
  473.         else
  474.         {
  475.             prev = p;
  476.         }
  477.         }
  478.         return res;
  479.     }       
  480. #ifdef _MSC_VER
  481.     template<typename A>
  482.     address_t address(typename A::pointer p)const
  483.     {       
  484.         pageid_t pn = (pageid_t)((size_type)((byte*)p - (byte*)pagepool_)/PAGESIZE);
  485.         A * alloc = GETALLOCTOR(A,(pagepool_ + pn)->buf);
  486.         return MAKEULONG(alloc->address(p),pn);
  487.     }
  488. #else
  489.     template<typename A,typename P>
  490.     address_t address(A*,P p)const
  491.     {
  492.          pageid_t pn = (pageid_t)((size_type)((byte*)p - (byte*)pagepool_)/PAGESIZE);
  493.          A * alloc = GETALLOCTOR(A,(pagepool_ + pn)->buf);
  494.          return MAKEULONG(alloc->address(p),pn);
  495.     }
  496. #endif
  497.     inline void * buffer(pageid_t pageid)
  498.     {
  499.         if(!inrange(pageid) )
  500.         return (void*)0;
  501.         return (void*)(pagepool_+pageid)->buf;
  502.     }   
  503.     inline page * get_page(pageid_t pageid)
  504.     {
  505.         if(!inrange(pageid) )
  506.         return 0;
  507.         return pagepool_ + pageid;      
  508.     }
  509.     static page_allocator & instance()
  510.     {
  511.         static page_allocator obj;
  512.         return obj;
  513.     }   
  514.     byte * base()const { return buf_;}
  515.     size_t size()constreturn size_;}
  516. private:
  517.     inline bool inrange(pageid_t pageid)const
  518.     {
  519.         return (pageid >= 0 && pageid < lastpage_);
  520.     }
  521.     inline void tidy()
  522.     {           
  523.         pageid_t prev = MAXPAGE;        
  524.         for(pageid_t i = 0;i < lastpage_;++i)
  525.         {
  526.         page * p =  pagepool_+ i;
  527.         p->prev = prev;
  528.         p->next = MAXPAGE;          
  529.         if(prev != MAXPAGE )
  530.         {
  531.             (pagepool_ + prev)->next = i;
  532.         }
  533.         prev = i;
  534.         }
  535.     }
  536. private:
  537.     L lock;
  538.     byte * buf_;
  539.     pageid_t * cursor_; 
  540.     page * pagepool_;
  541.     size_t size_;
  542.     pageid_t lastpage_;
  543. };
  544. }//namespace sm
  545. #endif //_MEMORY_HPP_

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值