206 lines
5.7 KiB
C++
206 lines
5.7 KiB
C++
/*
|
|
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 <cat/Singleton.hpp>
|
|
#include <memory>
|
|
#include <xstring>
|
|
#include <sstream>
|
|
|
|
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<RegionAllocator>
|
|
{
|
|
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<class T>
|
|
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<class T> T *AcquireBuffer(u32 extra_bytes = 0)
|
|
{
|
|
return reinterpret_cast<T*>( 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<typename T>
|
|
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<typename S>
|
|
struct rebind
|
|
{
|
|
typedef STLRegionAllocator<S> other;
|
|
};
|
|
|
|
pointer address(reference X) const
|
|
{
|
|
return &X;
|
|
}
|
|
|
|
const_pointer address(const_reference X) const
|
|
{
|
|
return &X;
|
|
}
|
|
|
|
STLRegionAllocator() throw ()
|
|
{
|
|
}
|
|
|
|
template<typename S>
|
|
STLRegionAllocator(const STLRegionAllocator<S> &cp) throw ()
|
|
{
|
|
}
|
|
|
|
template<typename S>
|
|
STLRegionAllocator<T> &operator=(const STLRegionAllocator<S> &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<typename S>
|
|
bool operator==(STLRegionAllocator <S> const &) const throw()
|
|
{
|
|
return true;
|
|
}
|
|
|
|
template<typename S>
|
|
bool operator!=(STLRegionAllocator <S> const &) const throw()
|
|
{
|
|
return false;
|
|
}
|
|
};
|
|
|
|
// Common usage typedefs for using RegionAllocator as the STL allocator
|
|
typedef std::basic_ostringstream<char, std::char_traits<char>, STLRegionAllocator<char> > region_ostringstream;
|
|
typedef std::basic_string<char, std::char_traits<char>, STLRegionAllocator<char> > 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
|