📄 bitmap_allocator.h
字号:
else __len = __half; } return __first; } template<typename _InputIterator, typename _Predicate> inline _InputIterator __find_if(_InputIterator __first, _InputIterator __last, _Predicate __p) { while (__first != __last && !__p(*__first)) ++__first; return __first; } /** @brief The number of Blocks pointed to by the address pair * passed to the function. */ template<typename _AddrPair> inline size_t __num_blocks(_AddrPair __ap) { return (__ap.second - __ap.first) + 1; } /** @brief The number of Bit-maps pointed to by the address pair * passed to the function. */ template<typename _AddrPair> inline size_t __num_bitmaps(_AddrPair __ap) { return __num_blocks(__ap) / size_t(bits_per_block); } // _Tp should be a pointer type. template<typename _Tp> class _Inclusive_between : public std::unary_function<typename std::pair<_Tp, _Tp>, bool> { typedef _Tp pointer; pointer _M_ptr_value; typedef typename std::pair<_Tp, _Tp> _Block_pair; public: _Inclusive_between(pointer __ptr) : _M_ptr_value(__ptr) { } bool operator()(_Block_pair __bp) const throw() { if (std::less_equal<pointer>()(_M_ptr_value, __bp.second) && std::greater_equal<pointer>()(_M_ptr_value, __bp.first)) return true; else return false; } }; // Used to pass a Functor to functions by reference. template<typename _Functor> class _Functor_Ref : public std::unary_function<typename _Functor::argument_type, typename _Functor::result_type> { _Functor& _M_fref; public: typedef typename _Functor::argument_type argument_type; typedef typename _Functor::result_type result_type; _Functor_Ref(_Functor& __fref) : _M_fref(__fref) { } result_type operator()(argument_type __arg) { return _M_fref(__arg); } }; /** @class _Ffit_finder bitmap_allocator.h bitmap_allocator.h * * @brief The class which acts as a predicate for applying the * first-fit memory allocation policy for the bitmap allocator. */ // _Tp should be a pointer type, and _Alloc is the Allocator for // the vector. template<typename _Tp> class _Ffit_finder : public std::unary_function<typename std::pair<_Tp, _Tp>, bool> { typedef typename std::pair<_Tp, _Tp> _Block_pair; typedef typename balloc::__mini_vector<_Block_pair> _BPVector; typedef typename _BPVector::difference_type _Counter_type; size_t* _M_pbitmap; _Counter_type _M_data_offset; public: _Ffit_finder() : _M_pbitmap(0), _M_data_offset(0) { } bool operator()(_Block_pair __bp) throw() { // Set the _rover to the last physical location bitmap, // which is the bitmap which belongs to the first free // block. Thus, the bitmaps are in exact reverse order of // the actual memory layout. So, we count down the bimaps, // which is the same as moving up the memory. // If the used count stored at the start of the Bit Map headers // is equal to the number of Objects that the current Block can // store, then there is definitely no space for another single // object, so just return false. _Counter_type __diff = __gnu_cxx::balloc::__num_bitmaps(__bp); if (*(reinterpret_cast<size_t*> (__bp.first) - (__diff + 1)) == __gnu_cxx::balloc::__num_blocks(__bp)) return false; size_t* __rover = reinterpret_cast<size_t*>(__bp.first) - 1; for (_Counter_type __i = 0; __i < __diff; ++__i) { _M_data_offset = __i; if (*__rover) { _M_pbitmap = __rover; return true; } --__rover; } return false; } size_t* _M_get() const throw() { return _M_pbitmap; } _Counter_type _M_offset() const throw() { return _M_data_offset * size_t(bits_per_block); } }; /** @class _Bitmap_counter bitmap_allocator.h bitmap_allocator.h * * @brief The bitmap counter which acts as the bitmap * manipulator, and manages the bit-manipulation functions and * the searching and identification functions on the bit-map. */ // _Tp should be a pointer type. template<typename _Tp> class _Bitmap_counter { typedef typename balloc::__mini_vector<typename std::pair<_Tp, _Tp> > _BPVector; typedef typename _BPVector::size_type _Index_type; typedef _Tp pointer; _BPVector& _M_vbp; size_t* _M_curr_bmap; size_t* _M_last_bmap_in_block; _Index_type _M_curr_index; public: // Use the 2nd parameter with care. Make sure that such an // entry exists in the vector before passing that particular // index to this ctor. _Bitmap_counter(_BPVector& Rvbp, long __index = -1) : _M_vbp(Rvbp) { this->_M_reset(__index); } void _M_reset(long __index = -1) throw() { if (__index == -1) { _M_curr_bmap = 0; _M_curr_index = static_cast<_Index_type>(-1); return; } _M_curr_index = __index; _M_curr_bmap = reinterpret_cast<size_t*> (_M_vbp[_M_curr_index].first) - 1; _BALLOC_ASSERT(__index <= (long)_M_vbp.size() - 1); _M_last_bmap_in_block = _M_curr_bmap - ((_M_vbp[_M_curr_index].second - _M_vbp[_M_curr_index].first + 1) / size_t(bits_per_block) - 1); } // Dangerous Function! Use with extreme care. Pass to this // function ONLY those values that are known to be correct, // otherwise this will mess up big time. void _M_set_internal_bitmap(size_t* __new_internal_marker) throw() { _M_curr_bmap = __new_internal_marker; } bool _M_finished() const throw() { return(_M_curr_bmap == 0); } _Bitmap_counter& operator++() throw() { if (_M_curr_bmap == _M_last_bmap_in_block) { if (++_M_curr_index == _M_vbp.size()) _M_curr_bmap = 0; else this->_M_reset(_M_curr_index); } else --_M_curr_bmap; return *this; } size_t* _M_get() const throw() { return _M_curr_bmap; } pointer _M_base() const throw() { return _M_vbp[_M_curr_index].first; } _Index_type _M_offset() const throw() { return size_t(bits_per_block) * ((reinterpret_cast<size_t*>(this->_M_base()) - _M_curr_bmap) - 1); } _Index_type _M_where() const throw() { return _M_curr_index; } }; /** @brief Mark a memory address as allocated by re-setting the * corresponding bit in the bit-map. */ inline void __bit_allocate(size_t* __pbmap, size_t __pos) throw() { size_t __mask = 1 << __pos; __mask = ~__mask; *__pbmap &= __mask; } /** @brief Mark a memory address as free by setting the * corresponding bit in the bit-map. */ inline void __bit_free(size_t* __pbmap, size_t __pos) throw() { size_t __mask = 1 << __pos; *__pbmap |= __mask; } } // namespace balloc /** @brief Generic Version of the bsf instruction. */ inline size_t _Bit_scan_forward(size_t __num) { return static_cast<size_t>(__builtin_ctzl(__num)); } /** @class free_list bitmap_allocator.h bitmap_allocator.h * * @brief The free list class for managing chunks of memory to be * given to and returned by the bitmap_allocator. */ class free_list { typedef size_t* value_type; typedef balloc::__mini_vector<value_type> vector_type; typedef vector_type::iterator iterator; struct _LT_pointer_compare { bool operator()(const size_t* __pui, const size_t __cui) const throw() { return *__pui < __cui; } };#if defined __GTHREADS _Mutex* _M_get_mutex() { static _Mutex _S_mutex; return &_S_mutex; }#endif vector_type& _M_get_free_list() { static vector_type _S_free_list; return _S_free_list; } /** @brief Performs validation of memory based on their size. * * @param __addr The pointer to the memory block to be * validated. * * @detail Validates the memory block passed to this function and * appropriately performs the action of managing the free list of * blocks by adding this block to the free list or deleting this * or larger blocks from the free list. */ void _M_validate(size_t* __addr) throw() { vector_type& __free_list = _M_get_free_list(); const vector_type::size_type __max_size = 64; if (__free_list.size() >= __max_size) { // Ok, the threshold value has been reached. We determine // which block to remove from the list of free blocks. if (*__addr >= *__free_list.back()) { // Ok, the new block is greater than or equal to the // last block in the list of free blocks. We just free // the new block. ::operator delete(static_cast<void*>(__addr)); return; } else { // Deallocate the last block in the list of free lists, // and insert the new one in it's correct position. ::operator delete(static_cast<void*>(__free_list.back())); __free_list.pop_back(); } } // Just add the block to the list of free lists unconditionally. iterator __temp = __gnu_cxx::balloc::__lower_bound (__free_list.begin(), __free_list.end(), *__addr, _LT_pointer_compare()); // We may insert the new free list before _temp; __free_list.insert(__temp, __addr); } /** @brief Decides whether the wastage of memory is acceptable for * the current memory request and returns accordingly. * * @param __block_size The size of the block available in the free * list. * * @param __required_size The required size of the memory block. * * @return true if the wastage incurred is acceptable, else returns * false. */ bool _M_should_i_give(size_t __block_size, size_t __required_size) throw() { const size_t __max_wastage_percentage = 36; if (__block_size >= __required_size && (((__block_size - __required_size) * 100 / __block_size) < __max_wastage_percentage)) return true; else return false; } public: /** @brief This function returns the block of memory to the * internal free list. * * @param __addr The pointer to the memory block that was given * by a call to the _M_get function. */ inline void _M_insert(size_t* __addr) throw() {#if defined __GTHREADS _Auto_Lock __bfl_lock(_M_get_mutex());#endif // Call _M_validate to decide what should be done with // this particular free list. this->_M_validate(reinterpret_cast<size_t*>(__addr) - 1); // See discussion as to why this is 1! } /** @brief This function gets a block of memory of the specified * size from the free list. * * @param __sz The size in bytes of the memory required. * * @return A pointer to the new memory block of size at least * equal to that requested. */ size_t* _M_get(size_t __sz) throw(std::bad_alloc); /** @brief This function just clears the internal Free List, and * gives back all the memory to the OS. */ void _M_clear(); }; // Forward declare the class. template<typename _Tp> class bitmap_allocator; // Specialize for void: template<> class bitmap_allocator<void> { public: typedef void* pointer; typedef const void* const_pointer; // Reference-to-void members are impossible. typedef void value_type; template<typename _Tp1> struct rebind { typedef bitmap_allocator<_Tp1> other; }; }; template<typename _Tp>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -