/* Copyright (c) 2009-2010 Christopher A. Taylor. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of LibCat nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef CAT_REGION_ALLOCATOR_HPP #define CAT_REGION_ALLOCATOR_HPP #include #include #include #include namespace cat { // A region-based allocator that is lock-free, supporting // a range of allocation block sizes that are pre-allocated // in a pre-determined way, tuned to the application. class RegionAllocator : public Singleton { CAT_SINGLETON(RegionAllocator); protected: struct RegionInfoHead { u32 next_bitmap_entry; }; struct RegionInfo : public RegionInfoHead { volatile u32 bitmap[1]; }; // 64, 128, 256, 512, 1024, 2048 only static const u32 REGION_COUNT = 6; static const u32 BLOCK_SIZE[REGION_COUNT]; u32 bytes_overall; u32 blocks_per_region[REGION_COUNT]; u32 bitmap_dwords[REGION_COUNT]; u8 *regions[REGION_COUNT]; RegionInfo *region_info[REGION_COUNT]; //u32 errors; public: bool Valid(); void Shutdown(); public: void *Acquire(u32 bytes); void *Resize(void *ptr, u32 bytes); void Release(void *ptr); template CAT_INLINE void Delete(T *ptr) { ptr->~T(); Release(ptr); } // Acquires a buffer from the allocator that is the size of the type. // It further allocates a number of extra bytes beyond the end of the buffer. // Release the buffer with: // RegionAllocator::ii->Release(ptr); template T *AcquireBuffer(u32 extra_bytes = 0) { return reinterpret_cast( Acquire(sizeof(T) + extra_bytes) ); } }; // Use STLRegionAllocator in place of the standard STL allocator // to make use of the RegionAllocator in STL types. Some common // usage typedefs follow this class definition below. template class STLRegionAllocator { public: typedef size_t size_type; typedef size_t difference_type; typedef T *pointer; typedef const T *const_pointer; typedef T &reference; typedef const T &const_reference; typedef T value_type; template struct rebind { typedef STLRegionAllocator other; }; pointer address(reference X) const { return &X; } const_pointer address(const_reference X) const { return &X; } STLRegionAllocator() throw () { } template STLRegionAllocator(const STLRegionAllocator &cp) throw () { } template STLRegionAllocator &operator=(const STLRegionAllocator &cp) throw () { return *this; } pointer allocate(size_type Count, const void *Hint = 0) { return (pointer)RegionAllocator::ii->Acquire((u32)Count * sizeof(T)); } void deallocate(pointer Ptr, size_type Count) { RegionAllocator::ii->Release(Ptr); } void construct(pointer Ptr, const T &Val) { std::_Construct(Ptr, Val); } void destroy(pointer Ptr) { std::_Destroy(Ptr); } size_type max_size() const { return 0x00FFFFFF; } template bool operator==(STLRegionAllocator const &) const throw() { return true; } template bool operator!=(STLRegionAllocator const &) const throw() { return false; } }; // Common usage typedefs for using RegionAllocator as the STL allocator typedef std::basic_ostringstream, STLRegionAllocator > region_ostringstream; typedef std::basic_string, STLRegionAllocator > region_string; } // namespace cat // Provide placement new constructor and delete pair to allow for // an easy syntax to create objects from the RegionAllocator: // T *a = new (RegionAllocator::ii) T(); // The object can be freed with: // RegionAllocator::ii->Delete(a); // Which insures that the destructor is called before freeing memory inline void *operator new(size_t bytes, cat::RegionAllocator *allocator) { return allocator->Acquire((cat::u32)bytes); } inline void operator delete(void *ptr, cat::RegionAllocator *allocator) { allocator->Release(ptr); } #endif // CAT_REGION_ALLOCATOR_HPP