Index: src/misc/fixedsizearray.hpp =================================================================== --- src/misc/fixedsizearray.hpp (Revision 18673) +++ src/misc/fixedsizearray.hpp (Arbeitskopie) @@ -9,100 +9,194 @@ /** @file fixedsizearray.hpp A fixed size array that doesn't create items until needed. */ -#ifndef FIXEDSIZEARRAY_HPP -#define FIXEDSIZEARRAY_HPP +#ifndef FIXEDSIZEARRAY_HPP +#define FIXEDSIZEARRAY_HPP - /** fixed size array * Upon construction it preallocates fixed size block of memory - * for all items, but doesn't construct them. Item's construction - * is delayed. */ -template -struct CFixedSizeArrayT { - /** the only member of fixed size array is pointer to the block - * of C array of items. Header can be found on the offset -sizeof(CHdr). */ - Titem_ *m_items; + * for all items, but doesn't construct them. Items construction + * is delayed. By using the copy constructor the data will be + * shared between the arrays. + * + * @note The only member of fixed size array is pointer to the + * block of C array of items. Header is a "part" of data + * and can be found on the offset -sizeof(ArrayHeader). + * + * @param T The type of the items stored + * @param C The maximum number of items to be stored in the array + */ +template +struct FixedSizeArray { +protected: + T *data; ///< The pointer to the first item /** header for fixed size array */ - struct CHdr + struct ArrayHeader { - int m_num_items; ///< number of items in the array - int m_ref_cnt; ///< block reference counter (used by copy constructor and by destructor) + uint items; ///< number of items in the array + uint reference_count; ///< block reference counter (used by copy constructor and by destructor) }; - /* make types and constants visible from outside */ - typedef Titem_ Titem; // type of array item + static const uint TSize = sizeof(T); // size of item + static const uint HeaderSize = sizeof(ArrayHeader); // size of header - static const int Tcapacity = Tcapacity_; // the array capacity (maximum size) - static const int TitemSize = sizeof(Titem_); // size of item - static const int ThdrSize = sizeof(CHdr); // size of header +public: + /** + * Default constructor. Preallocate memory for items AND header, + * but don't construct items. After that initialize header. + */ + FixedSizeArray() + { + this->data = (T*)((MallocT(this->HeaderSize + C * this->TSize)) + this->HeaderSize); - /** Default constructor. Preallocate space for items and header, then initialize header. */ - CFixedSizeArrayT() - { - /* allocate block for header + items (don't construct items) */ - m_items = (Titem*)((MallocT(ThdrSize + Tcapacity * sizeof(Titem))) + ThdrSize); - SizeRef() = 0; // initial number of items - RefCnt() = 1; // initial reference counter + /* Set initial header values */ + this->Header().items = 0; + this->Header().reference_count = 1; } - /** Copy constructor. Preallocate space for items and header, then initialize header. */ - CFixedSizeArrayT(const CFixedSizeArrayT& src) + /** + * Copy constructor. Add the reference to the source array data. + * Share memory block (header + items) with the source array. + * + * @param src The source array + */ + FixedSizeArray(const FixedSizeArray& src) { - /* share block (header + items) with the source array */ - m_items = src.m_items; - RefCnt()++; // now we share block with the source + this->data = src.data; + this->Header().reference_count++; } - /** destroy remaining items and free the memory block */ - ~CFixedSizeArrayT() + /** + * Destroy remaining items and free the memory block or just release + * reference to data if the array is shared. + */ + ~FixedSizeArray() { /* release one reference to the shared block */ - if ((--RefCnt()) > 0) return; // and return if there is still some owner + this->Header().reference_count--; - Clear(); + /* return if there is still some owner */ + if (this->Header().reference_count > 0) return; + + this->Clear(); + /* free the memory block occupied by items */ - free(((int8*)m_items) - ThdrSize); - m_items = NULL; + free(((byte*)this->data) - this->HeaderSize); + this->data = NULL; } - /** Clear (destroy) all items */ +protected: + /** + * Get the header of the array. + * + * @return reference to the array header + */ + FORCEINLINE ArrayHeader& Header() + { + return *(ArrayHeader*)(((byte*)this->data) - this->HeaderSize); + } + + /** + * Get the header of the array. (const) + * + * @return reference to the array header + */ + FORCEINLINE const ArrayHeader& Header() const + { + return *(ArrayHeader*)(((byte*)this->data) - this->HeaderSize); + } + +public: + /** + * Get the number of items in the list. + */ + FORCEINLINE uint Size() const + { + return this->Header().items; + } + + /** + * Clear (destroy) all items by using their destructor. + */ FORCEINLINE void Clear() { - /* walk through all allocated items backward and destroy them */ - for (Titem *pItem = &m_items[Size() - 1]; pItem >= m_items; pItem--) { - pItem->~Titem_(); + /* Walk through all allocated items backward and destroy them. */ + for (T *pItem = &this->data[this->Size() - 1]; pItem >= this->data; pItem--) { + pItem->~T(); } - /* number of items become zero */ - SizeRef() = 0; + + this->Header().items = 0; } -protected: - /** return reference to the array header (non-const) */ - FORCEINLINE CHdr& Hdr() { return *(CHdr*)(((int8*)m_items) - ThdrSize); } - /** return reference to the array header (const) */ - FORCEINLINE const CHdr& Hdr() const { return *(CHdr*)(((int8*)m_items) - ThdrSize); } - /** return reference to the block reference counter */ - FORCEINLINE int& RefCnt() { return Hdr().m_ref_cnt; } - /** return reference to number of used items */ - FORCEINLINE int& SizeRef() { return Hdr().m_num_items; } -public: - /** return number of used items */ - FORCEINLINE int Size() const { return Hdr().m_num_items; } - /** return true if array is full */ - FORCEINLINE bool IsFull() const { return Size() >= Tcapacity; }; - /** return true if array is empty */ - FORCEINLINE bool IsEmpty() const { return Size() <= 0; }; - /** index validation */ - FORCEINLINE void CheckIdx(int idx) const { assert(idx >= 0); assert(idx < Size()); } - /** add (allocate), but don't construct item */ - FORCEINLINE Titem& AddNC() { assert(!IsFull()); return m_items[SizeRef()++]; } - /** add and construct item using default constructor */ - FORCEINLINE Titem& Add() { Titem& item = AddNC(); new(&item)Titem; return item; } - /** return item by index (non-const version) */ - FORCEINLINE Titem& operator [] (int idx) { CheckIdx(idx); return m_items[idx]; } - /** return item by index (const version) */ - FORCEINLINE const Titem& operator [] (int idx) const { CheckIdx(idx); return m_items[idx]; } + /** + * Tests whether the array is full. + * + * @return true if array is full + */ + FORCEINLINE bool IsFull() const + { + return this->Size() >= C; + } + + /** + * Tests whether the array is empty. + * + * @return true if array is empty + */ + FORCEINLINE bool IsEmpty() const + { + return this->Size() == 0; + } + + /** + * Add ("allocate"), but don't construct an item + * and return it. + * + * @return pointer to the memory for the new item + */ + FORCEINLINE T& AddNC() + { + assert(this->Size() < C); + return this->data[this->Header().items++]; + } + + /** + * Add and construct item using the default + * constructor and return it. + * + * @return pointer to the new item */ + FORCEINLINE T& Add() + { + assert(this->Size() < C); + T& item = this->data[this->Size()]; + this->Header().items++; + new (&item)T; + return item; + } + + /** + * Get item "number" + * + * @param index the positon of the item + * @return the item + */ + FORCEINLINE T &operator[](uint index) + { + assert(index < this->Size()); + return this->data[index]; + } + + /** + * Get item "number" (const) + * + * @param index the positon of the item + * @return the item + */ + FORCEINLINE const T &operator[](uint index) const + { + assert(index < this->Size()); + return this->data[index]; + } }; #endif /* FIXEDSIZEARRAY_HPP */ Index: src/misc/array.hpp =================================================================== --- src/misc/array.hpp (Revision 18673) +++ src/misc/array.hpp (Arbeitskopie) @@ -20,8 +20,8 @@ class CArrayT { public: typedef Titem_ Titem; ///< Titem is now visible from outside - typedef CFixedSizeArrayT CSubArray; ///< inner array - typedef CFixedSizeArrayT CSuperArray; ///< outer array + typedef FixedSizeArray CSubArray; ///< inner array + typedef FixedSizeArray CSuperArray; ///< outer array protected: CSuperArray m_a; ///< array of arrays of items @@ -38,7 +38,7 @@ /** Return actual number of items */ FORCEINLINE int Size() const { - int super_size = m_a.Size(); + uint super_size = m_a.Size(); if (super_size == 0) return 0; int sub_size = m_a[super_size - 1].Size(); return (super_size - 1) * Tblock_size + sub_size; @@ -50,7 +50,7 @@ /** return first sub-array with free space for new item */ FORCEINLINE CSubArray& FirstFreeSubArray() { - int super_size = m_a.Size(); + uint super_size = m_a.Size(); if (super_size > 0) { CSubArray& sa = m_a[super_size - 1]; if (!sa.IsFull()) return sa;