工作中要用到一个基于共享内存的HASH TABLE,也就是数据和HASH TABLE自身的成员变量都要放到共享内存上,自然内存分配也要自己写。
先贴出代码,感兴趣的我们在讨论:)
先贴出代码,感兴趣的我们在讨论:)
- #ifndef _ALLOCATORS_HPP_
- #define _ALLOCATORS_HPP_
- #include <cassert>
- #define MAXPAGE ((pageid_t)0xFFFFFFFF)
- #define PAGESIZE (1024 * 16)
- #if defined(__LP64__) || defined(__64BIT__) || defined(_LP64) || defined (_AMD64__)|| defined(__IA64__)
- # define MAXPOSITION ((size_t)0xFFFFFFFFFFFFFFFF)
- # define SHIFTBITS 32
- typedef unsigned int WORD;
- # define MASKBITS 0xFFFFFFFF
- #else
- # define MAXPOSITION ((size_t)0xFFFFFFFF)
- # define SHIFTBITS 16
- typedef unsigned short WORD;
- # define MASKBITS 0xFFFF
- #endif
- #define ALLOC_OFFSET(p) *((offset_type*)p)
- #define ALLOCATE(A,alloc,p) A * alloc = (A*)((byte*)p + ALLOC_OFFSET(p));construct(alloc)
- #define GETALLOCTOR(A,p) (A*)( (byte*)p + ALLOC_OFFSET(p))
- #define SETALLOCOFFSET(p,offset) *((offset_type*)p)=(offset)
- #define ALLOC_SIZE(A,p) (PAGESIZE - ALLOC_OFFSET(p)-sizeof(A))
- #define MAKEULONG(l,h) ((size_t)(((WORD)((size_t)(l) & MASKBITS)) | ((size_t)((WORD)((size_t)(h) & MASKBITS))) << SHIFTBITS))
- #define HIWORD(a) ((WORD)((a >> SHIFTBITS ) & MASKBITS))
- #define LOWORD(a) ((WORD)(a & MASKBITS))
- namespace sm
- {
- struct outof_memory{};
- struct page_outof_range{};
- template<typename T>
- void construct(T * ptr)
- {
- ::new (ptr)T();
- }
- template<typename T,typename V>
- void construct(T * ptr, const V & val)
- {
- ::new (ptr)T(val);
- }
- template<typename T,typename A1,typename A2>
- void construct(T * ptr, const A1 & a1,const A2 & a2)
- {
- ::new (ptr)T(a1,a2);
- }
- template<typename T>
- void destroy(T * ptr)
- {
- ptr->~T();
- }
- template<int bits> struct page_traits;
- template<>
- struct page_traits<8>
- {
- typedef size_t size_type;
- typedef unsigned int offset_type;
- typedef unsigned int pageid_type;
- typedef size_t address_type;
- typedef unsigned char byte;
- enum{ BUFSIZE = PAGESIZE - sizeof(pageid_type) * 2 };
- };
- template<>
- struct page_traits<4>
- {
- typedef size_t size_type;
- typedef unsigned int offset_type;
- typedef unsigned int pageid_type;
- typedef size_t address_type;
- typedef unsigned char byte;
- enum{ BUFSIZE = PAGESIZE - sizeof(pageid_type) * 2 };
- };
- template<class T>
- class allocator
- {
- public:
- typedef page_traits<sizeof(size_t)> page_traits_t;
- typedef typename page_traits_t::size_type size_type;
- typedef typename page_traits_t::offset_type offset_type;
- typedef typename page_traits_t::byte byte;
- typedef typename page_traits_t::address_type address_type;
- typedef T value_type;
- typedef T * pointer;
- struct memory_thunk
- {
- union
- {
- byte data[sizeof(value_type)];
- offset_type offset;
- };
- };
- public:
- template<class _Other>
- struct rebind
- {
- typedef allocator<_Other> other;
- };
- allocator()
- {}
- static size_type thunks_size(size_type n)
- {
- return (sizeof(memory_thunk) * n);
- }
- void open(size_type sz,bool init)
- {
- if( init )
- {
- cur_ = offset_type(0);
- last_ = (offset_type)( sz / sizeof(memory_thunk) ) - 1;
- tidy();
- }
- }
- inline bool exists(pointer p)const
- {
- if(!p)return false;
- memory_thunk * c = reinterpret_cast<memory_thunk*>(p);
- return (c < pool_ + last_ && c >= pool_);
- }
- inline pointer allocate()
- {
- if(cur_ < last_ )
- {
- memory_thunk * thunk = pool_+ cur_;
- cur_ = thunk->offset;
- return reinterpret_cast<pointer>( thunk );
- }
- return 0;
- }
- inline void deallocate(pointer p,size_type)
- {
- if(p && exists(p) )
- {
- memory_thunk * thunk = reinterpret_cast<memory_thunk*>( p );
- size_type pos = thunk - pool_;
- thunk->offset = cur_;
- cur_ = pos;
- }
- }
- inline offset_type address(pointer p)const
- {
- assert( p != 0 );
- assert( p >= (pointer)pool_ );
- assert( last_ > 0 );
- assert( (memory_thunk*)p < (pool_ + last_) );
- offset_type ret = offset_type(reinterpret_cast<memory_thunk*>(p)-pool_);
- assert( ret >=0 && ret < last_ );
- return ret;
- }
- inline pointer ptr(offset_type pos)const
- {
- assert( pos >=0 && pos < last_ );
- return reinterpret_cast<pointer>(const_cast<memory_thunk*>(pool_+pos));
- }
- inline void reset()
- {
- cur_ = 0;
- tidy();
- }
- size_type max_count()const
- {
- return last_;
- }
- bool empty()
- {
- return (capacity() == (size_t)last_);
- }
- size_t capacity()
- {
- offset_type n=0;
- offset_type pos = cur_;
- while(pos < last_ )
- {
- ++n;
- memory_thunk * thunk = pool_+ pos;
- pos = thunk->offset;
- }
- return (size_t)n;
- }
- private:
- void tidy()
- {
- assert(last_ > 0 );
- for(offset_type i = 0;i < last_;++i)
- {
- pool_[i].offset=i+1;
- }
- }
- private:
- offset_type cur_;
- offset_type last_;
- memory_thunk pool_[0];
- };
- template<class _Ty,class _Other>
- inline bool operator==(const allocator<_Ty>&, const allocator<_Other>&) throw()
- {
- return (true);
- }
- template<class _Ty,class _Other>
- inline bool operator!=(const allocator<_Ty>&, const allocator<_Other>&) throw()
- {
- return (false);
- }
- //
- //page_allocator
- ///
- template<typename L>
- class page_allocator
- {
- public:
- typedef page_traits<sizeof(size_t)> page_traits_t;
- typedef page_traits_t::size_type size_type;
- typedef page_traits_t::offset_type offset_type;
- typedef page_traits_t::pageid_type pageid_t;
- typedef page_traits_t::address_type address_t;
- typedef page_traits_t::byte byte;
- enum{ BUFSIZE = page_traits_t::BUFSIZE };
- struct page
- {
- pageid_t prev;
- pageid_t next;
- byte buf[BUFSIZE];
- };
- struct auto_page
- {
- pageid_t pageid;
- auto_page(pageid_t pageid):pageid(pageid)
- {}
- ~auto_page()
- {
- if(pageid != MAXPAGE)
- {
- page_allocator<L>::instance().deallocate(pageid);
- pageid = MAXPAGE;
- }
- }
- pageid_t release()
- {
- pageid_t ret = pageid;
- pageid = MAXPAGE;
- return ret;
- }
- };
- private:
- page_allocator()
- :lock(),buf_(0),cursor_(0),pagepool_(0),size_(0),lastpage_(0)
- {}
- page_allocator(page_allocator const&);
- page_allocator & operator = (page_allocator const&);
- public:
- struct iterator
- {
- page_allocator * pa_;
- pageid_t page_;
- iterator():pa_(0),page_(MAXPAGE){}
- iterator(page_allocator * a,pageid_t p):pa_(a),page_(p){}
- iterator(iterator const & other):pa_(other.pa_),page_(other.page_){}
- iterator & operator = ( iterator const & other)
- {
- pa_ = other.pa_;
- page_ = other.page_;
- return *this;
- }
- iterator & operator ++()
- {
- page_ = pa_->get_page(page_)->next;
- return *this;
- }
- iterator operator ++(int)
- {
- iterator tmp(*this);
- ++*this;
- return tmp;
- }
- iterator & operator --()
- {
- page_ = pa_->get_page(page_)->prev;
- return *this;
- }
- iterator operator --(int)
- {
- iterator tmp(*this);
- --*this;
- return tmp;
- }
- page & operator*()
- {
- assert( pa_ !=0 );
- assert( page_ != MAXPAGE);
- page * p = pa_->get_page(page_);
- return *p;
- }
- page const & operator *()const
- {
- assert( pa_ !=0 );
- assert( page_ != MAXPAGE);
- page * p = pa_->get_page(page_);
- return *p;
- }
- pageid_t get()const{ return page_;}
- bool operator == ( iterator const & other)
- {
- return (pa_ == other.pa_ && page_ == other.page_);
- }
- bool operator != ( iterator const & other)
- {
- return !(operator ==(other) );
- }
- };
- iterator get_iterator(pageid_t pn)
- {
- return iterator(this,pn);
- }
- iterator end()
- {
- return iterator(this,MAXPAGE);
- }
- iterator begin(pageid_t pn)
- {
- pageid_t tmp = MAXPAGE;
- while(pn != MAXPAGE )
- {
- tmp = pn;
- pn = get_page(tmp)->prev;
- }
- return iterator(this,tmp);
- }
- iterator rbein(pageid_t pn)
- {
- pageid_t tmp = MAXPAGE;
- while(pn != MAXPAGE )
- {
- tmp = pn;
- pn = get_page(tmp)->next;
- }
- return iterator(this,tmp);
- }
- size_t deallocate_page_list(pageid_t pageid)
- {
- iterator it = begin(pageid);
- if(it == end() ) return 0;
- pageid = it.get();
- size_t ret = 0;
- while(pageid != MAXPAGE )
- {
- pageid_t tmp = pageid;
- page * p = get_page(tmp);
- pageid = p->next;
- deallocate( tmp );
- ++ret;
- }
- return ret;
- }
- bool open(byte* buf,size_t sz)
- {
- buf_ = buf;
- size_ = sz;
- if(!buf ) return false;
- if( size_ < ( sizeof(pageid_t) + PAGESIZE ) )
- return false;
- pagepool_ = reinterpret_cast<page*>(buf_ + sizeof(pageid_t));
- lastpage_ = (pageid_t)(size_- sizeof(pageid_t)) / PAGESIZE;
- cursor_ = (pageid_t*)(buf_);
- return true;
- }
- bool create(byte* buf,size_t sz)
- {
- buf_ = buf;
- size_ = sz;
- if(!buf ) return false;
- if( size_ < ( sizeof(pageid_t)+ PAGESIZE ) )
- return false;
- pagepool_ = reinterpret_cast<page*>(buf_ + sizeof(pageid_t));
- lastpage_ = (pageid_t)(size_ - sizeof(pageid_t)) / PAGESIZE;
- cursor_ = (pageid_t*)(buf_);
- *cursor_ = 0;
- tidy();
- return true;
- }
- pageid_t allocate()
- {
- typename L::scoped_lock guard(lock);
- pageid_t ret = MAXPAGE;
- assert(cursor_ );
- assert(lastpage_ > 0 );
- assert( size_ > PAGESIZE );
- if( MAXPAGE != *cursor_ )
- {
- ret = *cursor_;
- assert( (pagepool_ + *cursor_)->prev ==MAXPAGE );
- pageid_t next = (pagepool_ + *cursor_)->next;
- if(next != MAXPAGE )
- {
- *cursor_ = next;
- (pagepool_ + next)->prev = MAXPAGE;
- }
- else
- {
- *cursor_ = MAXPAGE;
- }
- (pagepool_+ ret)->next = MAXPAGE;
- assert( (pagepool_+ ret)->prev == MAXPAGE );
- }
- return ret;
- }
- void deallocate(pageid_t pageid)
- {
- typename L::scoped_lock guard(lock);
- assert(cursor_ );
- assert(lastpage_ > 0 );
- assert( size_ > PAGESIZE );
- if(inrange(pageid) )
- {
- (pagepool_+ pageid)->prev = MAXPAGE;
- (pagepool_+ pageid)->next = *cursor_;
- if( *cursor_ != MAXPAGE)
- {
- assert( (pagepool_+ *cursor_)->prev == MAXPAGE );
- (pagepool_+ *cursor_)->prev = pageid;
- }
- *cursor_ = pageid;
- }
- }
- template<typename A>
- int gc(A*,pageid_t pageid)
- {
- int res = 0;
- //next
- assert( inrange(pageid) );
- pageid_t next = (pagepool_+ pageid)->next;
- while(next != MAXPAGE )
- {
- assert( inrange(next) );
- pageid_t n = (pagepool_+ next)->next;
- A * alloc =GETALLOCTOR(A,(pagepool_ + next)->buf);
- if( alloc->empty() )
- {
- pageid_t p = (pagepool_+ next)->prev;
- (pagepool_+ p)->next = n;
- if(n != MAXPAGE )
- {
- (pagepool_+ n)->prev = p;
- }
- (pagepool_+ next)->next = MAXPAGE;
- (pagepool_+ next)->prev = MAXPAGE;
- deallocate(next);
- ++res;
- next = n;
- }
- else
- {
- next = n;
- }
- }
- //prev
- pageid_t prev = (pagepool_+ pageid)->prev;
- while(prev != MAXPAGE )
- {
- assert( inrange(prev) );
- pageid_t p = (pagepool_+ prev)->prev;
- A * alloc =GETALLOCTOR(A,(pagepool_ + prev)->buf);
- if( alloc->empty() )
- {
- pageid_t n = (pagepool_+ prev)->next;
- (pagepool_+ n)->prev = p;
- if(p != MAXPAGE )
- {
- (pagepool_+ p)->next = n;
- }
- ++res;
- (pagepool_+ prev)->next = MAXPAGE;
- (pagepool_+ prev)->prev = MAXPAGE;
- deallocate(prev);
- prev = p;
- }
- else
- {
- prev = p;
- }
- }
- return res;
- }
- #ifdef _MSC_VER
- template<typename A>
- address_t address(typename A::pointer p)const
- {
- pageid_t pn = (pageid_t)((size_type)((byte*)p - (byte*)pagepool_)/PAGESIZE);
- A * alloc = GETALLOCTOR(A,(pagepool_ + pn)->buf);
- return MAKEULONG(alloc->address(p),pn);
- }
- #else
- template<typename A,typename P>
- address_t address(A*,P p)const
- {
- pageid_t pn = (pageid_t)((size_type)((byte*)p - (byte*)pagepool_)/PAGESIZE);
- A * alloc = GETALLOCTOR(A,(pagepool_ + pn)->buf);
- return MAKEULONG(alloc->address(p),pn);
- }
- #endif
- inline void * buffer(pageid_t pageid)
- {
- if(!inrange(pageid) )
- return (void*)0;
- return (void*)(pagepool_+pageid)->buf;
- }
- inline page * get_page(pageid_t pageid)
- {
- if(!inrange(pageid) )
- return 0;
- return pagepool_ + pageid;
- }
- static page_allocator & instance()
- {
- static page_allocator obj;
- return obj;
- }
- byte * base()const { return buf_;}
- size_t size()const{ return size_;}
- private:
- inline bool inrange(pageid_t pageid)const
- {
- return (pageid >= 0 && pageid < lastpage_);
- }
- inline void tidy()
- {
- pageid_t prev = MAXPAGE;
- for(pageid_t i = 0;i < lastpage_;++i)
- {
- page * p = pagepool_+ i;
- p->prev = prev;
- p->next = MAXPAGE;
- if(prev != MAXPAGE )
- {
- (pagepool_ + prev)->next = i;
- }
- prev = i;
- }
- }
- private:
- L lock;
- byte * buf_;
- pageid_t * cursor_;
- page * pagepool_;
- size_t size_;
- pageid_t lastpage_;
- };
- }//namespace sm
- #endif //_MEMORY_HPP_