// // Copyright (C) 2000-2002 Andrey Slepuhin // // libp++ is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 2 of the License, or // (at your option) any later version. // // libp++ is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with libp++; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // // $Source$ // $Revision$ // $Date$ // Author: Andrey Slepuhin #ifndef __pxx_heap_allocator_ih__ #define __pxx_heap_allocator_ih__ #include "pxx_heap_allocator.hh" #include "pxx_allocator.ih" namespace pxx { inline HeapAllocator::BlockHeader::BlockHeader ( BlockHeader* _prev, BlockHeader* _next, size_t _size /* = 0 */ ) : size (_size), prev (_prev), next (_next) {} inline void HeapAllocator::BlockHeader::remove () { prev->next = next; next->prev = prev; } inline uintptr_t HeapAllocator::BlockHeader::get_size () const { return size & ~((uintptr_t)(0x01)); } inline void HeapAllocator::BlockHeader::set_size (uintptr_t _size) { size = _size | 0x01; } inline HeapAllocator::FreeBlockList::FreeBlockList () : BlockHeader (this, this) {} inline HeapAllocator::BlockHeader* HeapAllocator::FreeBlockList::get () { if (next != this) { BlockHeader* p = next; p->remove(); return p; } else { return null; } } inline void HeapAllocator::FreeBlockList::put ( BlockHeader* _block ) { BlockHeader* last = prev; _block->next = this; _block->prev = last; last->next = _block; this->prev = _block; _block->size = size; } // // Returns (if possible) a real size (probably larger then given) // of memory block to be allocated inline size_t HeapAllocator::get_real_size (size_t _size) const { _size += sizeof(uintptr_t); if (_size < min_free_size) _size = min_free_size; return exps_of_two[get_order(_size)] - sizeof(uintptr_t); } inline size_t HeapAllocator::get_size (void const* const _ptr) const { BlockHeader* p = (BlockHeader*)ptr_sub_offset(_ptr, sizeof(uintptr_t)); return p->get_size() - sizeof(uintptr_t); } // // Returns (if possible) the start address of allocated block containing a // pointer, otherwise returns null inline void* HeapAllocator::get_block (void* _ptr) { size_t s = current_size; while (s >= min_free_size) { void* p = ptr_add_offset(start_addr, ptr_sub(_ptr, start_addr) & (~(s - 1))); if (((BlockHeader*)p)->size == (s | 0x01)) return ptr_add_offset(p, sizeof(uintptr_t)); s >>= 1; } return null; } // // The same as previous, but using block size inline void* HeapAllocator::get_block (void* _ptr, size_t _size) { _size += sizeof(uintptr_t); if (_size < min_free_size) _size = min_free_size ; _size = exps_of_two[get_order(_size)]; void* real_block = ptr_add_offset(start_addr, ptr_sub(_ptr, start_addr) & (~(_size - 1))); return ptr_add_offset(real_block, sizeof(uintptr_t)); } inline bool HeapAllocator::is_dyn_addr (void* _ptr) { return _ptr >= start_addr && _ptr < ptr_add_offset(start_addr, current_size); } } #endif // __pxx_heap_allocator_ih__