// Ryzom - MMORPG Framework // Copyright (C) 2010 Winch Gate Property Limited // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as // published by the Free Software Foundation, either version 3 of the // License, or (at your option) any later version. // // This program 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 Affero General Public License for more details. // // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . #ifndef FIXED_SIZE_INT_VECTOR_H #define FIXED_SIZE_INT_VECTOR_H #include "nel/misc/types_nl.h" #include "nel/misc/debug.h" /** * The low level data container used to store the data for a CDB instance. * This container is vector-like with the significant difference that the * size of the vector is assumed to be fixed. * A special custom allocator is used for managing data blocks allocated and freed here * NOTE: The custom allocator never returns memory to the system - it retains all RAM that it has ever allocated */ template class CFixedSizeIntVector { public: /// ctor CFixedSizeIntVector(); /// dtor - calls release() ~CFixedSizeIntVector(); /// init /// This metod sets the size of the container, allocating memory either from the free data buffer pool or, /// if need be, from system memory /// Initialises all container contents to 0 void init(uint32 size,const T& value); /// release /// free up the data buffer used by this container (return it to the free data buffer pool) void release(); /// stl classic size() accessor uint size() const; /// classic operator[] - includes a bounds check even in release builds T& operator[](uint32 index); /// classic const operator[] - includes a bounds check even in release builds const T& operator[](uint32 index) const; private: /// the size of the current data buffer uint32 _Size; /// the data buffer (a pointer to the data) typedef T* TDataBufferPtr; TDataBufferPtr _DataBuffer; private: // a vector of data buffers (there is no size info here - they are assumed to be all of the same size) // this data type is used to contain the vector of free (reusable) buffers of a given size typedef std::vector TDataBufferPtrVector; /// static method used to wrap a static map of size to TDataBufferPtrVector static TDataBufferPtrVector& getFreeDataBufferVector(uint32 size); /// static method used to wrap a static map of size to uint32 data buffer counter static uint32& getDataBufferCounter(uint32 size); }; typedef CFixedSizeIntVector CFixedSizeVectorSint64; typedef CFixedSizeIntVector CFixedSizeVectorUint64; typedef CFixedSizeIntVector CFixedSizeVectorSint32; typedef CFixedSizeIntVector CFixedSizeVectorUint32; typedef CFixedSizeIntVector CFixedSizeVectorSint16; typedef CFixedSizeIntVector CFixedSizeVectorUint16; template CFixedSizeIntVector::CFixedSizeIntVector(): _Size(0), _DataBuffer(NULL) { } template CFixedSizeIntVector::~CFixedSizeIntVector() { // free up our data buffer release(); } template void CFixedSizeIntVector::init(uint32 size,const T& value) { // make sure we are not already initialised nlassert(_Size==0); // setup the new size _Size=size; nlassert(_Size!=0); // if there's a spare data buffer of this size kicking about then use it TDataBufferPtrVector& theFreeDataBufferPtrVector= getFreeDataBufferVector(_Size); if (!theFreeDataBufferPtrVector.empty()) { // there are spare data buffers of this size so pop the next one off the back of the buffer vector _DataBuffer= theFreeDataBufferPtrVector.back(); theFreeDataBufferPtrVector.pop_back(); } else { // no spare buffer of this size was available so allocate a new one uint32& theDataBufferCounter= getDataBufferCounter(_Size); ++theDataBufferCounter; nldebug("CFixedSizeDataVector_resize allocating a new buffer of size %u x %u (%u buffers in all)",_Size,sizeof(T),theDataBufferCounter); _DataBuffer= new T[_Size]; nlassert(_DataBuffer!=NULL); } // clear out the data in the buffer for (uint32 i=_Size;i--;) { _DataBuffer[i]= value; } } template void CFixedSizeIntVector::release() { // if we have a data buffer then add it to the relevant free data buffer vector in the free data buffer pool if (_DataBuffer!=NULL) { getFreeDataBufferVector(_Size).push_back(_DataBuffer); } _DataBuffer= NULL; _Size= 0; } template T& CFixedSizeIntVector::operator[](uint32 index) { // test for array overflows if (index>=_Size) nlerror("Array overflow in Client Property Database"); return _DataBuffer[index]; } template const T& CFixedSizeIntVector::operator[](uint32 index) const { // delegate to the non-const operator[] return const_cast(this)->operator[](index); } template uint CFixedSizeIntVector::size() const { return _Size; } template std::vector& CFixedSizeIntVector::getFreeDataBufferVector(uint32 size) { // a static map of buffer size to vector of free buffers of this size typedef std::map TFreeDataBufferVectors; static TFreeDataBufferVectors freeDataBufferVectors; return freeDataBufferVectors[size]; } template uint32& CFixedSizeIntVector::getDataBufferCounter(uint32 size) { // a static map of buffer size to counter of buffers of this size typedef std::map TDataBufferCounters; static TDataBufferCounters dataBufferCounters; return dataBufferCounters[size]; } #endif // FIXED_SIZE_INT_VECTOR_H