Home | History | Annotate | Download | only in decpp
      1 #ifndef _DEPOOLARRAY_HPP
      2 #define _DEPOOLARRAY_HPP
      3 /*-------------------------------------------------------------------------
      4  * drawElements C++ Base Library
      5  * -----------------------------
      6  *
      7  * Copyright 2014 The Android Open Source Project
      8  *
      9  * Licensed under the Apache License, Version 2.0 (the "License");
     10  * you may not use this file except in compliance with the License.
     11  * You may obtain a copy of the License at
     12  *
     13  *      http://www.apache.org/licenses/LICENSE-2.0
     14  *
     15  * Unless required by applicable law or agreed to in writing, software
     16  * distributed under the License is distributed on an "AS IS" BASIS,
     17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     18  * See the License for the specific language governing permissions and
     19  * limitations under the License.
     20  *
     21  *//*!
     22  * \file
     23  * \brief Array template backed by memory pool.
     24  *//*--------------------------------------------------------------------*/
     25 
     26 #include "deDefs.hpp"
     27 #include "deMemPool.hpp"
     28 #include "deInt32.h"
     29 
     30 #include <iterator>
     31 
     32 namespace de
     33 {
     34 
     35 //! Self-test for PoolArray
     36 void PoolArray_selfTest (void);
     37 
     38 template<typename T, deUint32 Alignment>
     39 class PoolArrayConstIterator;
     40 
     41 template<typename T, deUint32 Alignment>
     42 class PoolArrayIterator;
     43 
     44 /*--------------------------------------------------------------------*//*!
     45  * \brief Array template backed by memory pool
     46  *
     47  * \note Memory in PoolArray is not contiguous so pointer arithmetic
     48  *       to access next element(s) doesn't work.
     49  * \todo [2013-02-11 pyry] Make elements per page template argument.
     50  *//*--------------------------------------------------------------------*/
     51 template<typename T, deUint32 Alignment = (sizeof(T) > sizeof(void*) ? (deUint32)sizeof(void*) : (deUint32)sizeof(T))>
     52 class PoolArray
     53 {
     54 public:
     55 	typedef PoolArrayIterator<T, Alignment>			Iterator;
     56 	typedef PoolArrayConstIterator<T, Alignment>	ConstIterator;
     57 
     58 	typedef Iterator								iterator;
     59 	typedef ConstIterator							const_iterator;
     60 
     61 	explicit		PoolArray			(MemPool* pool);
     62 					PoolArray			(MemPool* pool, const PoolArray<T, Alignment>& other);
     63 					~PoolArray			(void);
     64 
     65 	void			clear				(void);
     66 
     67 	void			reserve				(deUintptr capacity);
     68 	void			resize				(deUintptr size);
     69 	void			resize				(deUintptr size, const T& value);
     70 
     71 	deUintptr		size				(void) const			{ return m_numElements;		}
     72 	bool			empty				(void) const			{ return m_numElements == 0;}
     73 
     74 	void			pushBack			(const T& value);
     75 	T				popBack				(void);
     76 
     77 	const T&		at					(deIntptr ndx) const	{ return *getPtr(ndx);		}
     78 	T&				at					(deIntptr ndx)			{ return *getPtr(ndx);		}
     79 
     80 	const T&		operator[]			(deIntptr ndx) const	{ return at(ndx);			}
     81 	T&				operator[]			(deIntptr ndx)			{ return at(ndx);			}
     82 
     83 	Iterator		begin				(void)					{ return Iterator(this, 0);								}
     84 	Iterator		end					(void)					{ return Iterator(this, (deIntptr)m_numElements);		}
     85 
     86 	ConstIterator	begin				(void) const			{ return ConstIterator(this, 0);						}
     87 	ConstIterator	end					(void) const			{ return ConstIterator(this, (deIntptr)m_numElements);	}
     88 
     89 	const T&		front				(void) const			{ return at(0); }
     90 	T&				front				(void)					{ return at(0); }
     91 
     92 	const T&		back				(void) const			{ return at(m_numElements-1); }
     93 	T&				back				(void)					{ return at(m_numElements-1); }
     94 
     95 private:
     96 	enum
     97 	{
     98 		ELEMENTS_PER_PAGE_LOG2	= 4			//!< 16 elements per page.
     99 	};
    100 
    101 					PoolArray			(const PoolArray<T, Alignment>& other); // \note Default copy ctor is not allowed, use PoolArray(pool, copy) instead.
    102 
    103 	T*				getPtr				(deIntptr ndx) const;
    104 
    105 	MemPool*		m_pool;
    106 
    107 	deUintptr		m_numElements;			//!< Number of elements in the array.
    108 	deUintptr		m_capacity;				//!< Number of allocated elements in the array.
    109 
    110 	deUintptr		m_pageTableCapacity;	//!< Size of the page table.
    111 	void**			m_pageTable;			//!< Pointer to the page table.
    112 };
    113 
    114 template<typename T, deUint32 Alignment>
    115 class PoolArrayIteratorBase
    116 {
    117 public:
    118 						PoolArrayIteratorBase		(deUintptr ndx) : m_ndx(ndx) {}
    119 						~PoolArrayIteratorBase		(void) {}
    120 
    121 	deIntptr			getNdx						(void) const throw() { return m_ndx;	}
    122 
    123 protected:
    124 	deIntptr			m_ndx;
    125 };
    126 
    127 template<typename T, deUint32 Alignment>
    128 class PoolArrayConstIterator : public PoolArrayIteratorBase<T, Alignment>
    129 {
    130 public:
    131 											PoolArrayConstIterator		(void);
    132 											PoolArrayConstIterator		(const PoolArray<T, Alignment>* array, deIntptr ndx);
    133 											PoolArrayConstIterator		(const PoolArrayIterator<T, Alignment>& iterator);
    134 											~PoolArrayConstIterator		(void);
    135 
    136 	// \note Default assignment and copy-constructor are auto-generated.
    137 
    138 	const PoolArray<T, Alignment>*			getArray	(void) const throw() { return m_array;	}
    139 
    140 	// De-reference operators.
    141 	const T*								operator->	(void) const throw()			{ return &(*m_array)[this->m_ndx];		}
    142 	const T&								operator*	(void) const throw()			{ return (*m_array)[this->m_ndx];		}
    143 	const T&								operator[]	(deUintptr offs) const throw()	{ return (*m_array)[this->m_ndx+offs];	}
    144 
    145 	// Pre-increment and decrement.
    146 	PoolArrayConstIterator<T, Alignment>&	operator++	(void)	{ this->m_ndx += 1; return *this;	}
    147 	PoolArrayConstIterator<T, Alignment>&	operator--	(void)	{ this->m_ndx -= 1; return *this;	}
    148 
    149 	// Post-increment and decrement.
    150 	PoolArrayConstIterator<T, Alignment>	operator++	(int)	{ PoolArrayConstIterator<T, Alignment> copy(*this); this->m_ndx +=1; return copy; }
    151 	PoolArrayConstIterator<T, Alignment>	operator--	(int)	{ PoolArrayConstIterator<T, Alignment> copy(*this); this->m_ndx -=1; return copy; }
    152 
    153 	// Compound assignment.
    154 	PoolArrayConstIterator<T, Alignment>&	operator+=	(deIntptr offs)	{ this->m_ndx += offs; return *this; }
    155 	PoolArrayConstIterator<T, Alignment>&	operator-=	(deIntptr offs)	{ this->m_ndx -= offs; return *this; }
    156 
    157 	// Assignment from non-const.
    158 	PoolArrayConstIterator<T, Alignment>&	operator=	(const PoolArrayIterator<T, Alignment>& iter);
    159 
    160 private:
    161 	const PoolArray<T, Alignment>*			m_array;
    162 };
    163 
    164 template<typename T, deUint32 Alignment>
    165 class PoolArrayIterator : public PoolArrayIteratorBase<T, Alignment>
    166 {
    167 public:
    168 										PoolArrayIterator	(void);
    169 										PoolArrayIterator	(PoolArray<T, Alignment>* array, deIntptr ndx);
    170 										~PoolArrayIterator	(void);
    171 
    172 	// \note Default assignment and copy-constructor are auto-generated.
    173 
    174 	PoolArray<T, Alignment>*			getArray	(void) const throw() { return m_array;	}
    175 
    176 	// De-reference operators.
    177 	T*									operator->	(void) const throw()			{ return &(*m_array)[this->m_ndx];		}
    178 	T&									operator*	(void) const throw()			{ return (*m_array)[this->m_ndx];		}
    179 	T&									operator[]	(deUintptr offs) const throw()	{ return (*m_array)[this->m_ndx+offs];	}
    180 
    181 	// Pre-increment and decrement.
    182 	PoolArrayIterator<T, Alignment>&	operator++	(void)	{ this->m_ndx += 1; return *this;	}
    183 	PoolArrayIterator<T, Alignment>&	operator--	(void)	{ this->m_ndx -= 1; return *this;	}
    184 
    185 	// Post-increment and decrement.
    186 	PoolArrayIterator<T, Alignment>		operator++	(int)	{ PoolArrayIterator<T, Alignment> copy(*this); this->m_ndx +=1; return copy; }
    187 	PoolArrayIterator<T, Alignment>		operator--	(int)	{ PoolArrayIterator<T, Alignment> copy(*this); this->m_ndx -=1; return copy; }
    188 
    189 	// Compound assignment.
    190 	PoolArrayIterator<T, Alignment>&	operator+=	(deIntptr offs)	{ this->m_ndx += offs; return *this; }
    191 	PoolArrayIterator<T, Alignment>&	operator-=	(deIntptr offs)	{ this->m_ndx -= offs; return *this; }
    192 
    193 private:
    194 	PoolArray<T, Alignment>*			m_array;
    195 };
    196 
    197 // Initializer helper for array.
    198 template<typename T>
    199 struct PoolArrayElement
    200 {
    201 	static void constructDefault	(void* ptr)					{ new (ptr) T();	}	//!< Called for non-initialized memory.
    202 	static void	constructCopy		(void* ptr, const T& val)	{ new (ptr) T(val);	}	//!< Called for non-initialized memory when initial value is provided.
    203 	static void destruct			(T* ptr)					{ ptr->~T();		}	//!< Called when element is destructed.
    204 };
    205 
    206 // Specialization for basic types.
    207 #define DE_SPECIALIZE_POOL_ARRAY_ELEMENT_BASIC_TYPE(TYPE)							\
    208 template<> struct PoolArrayElement<TYPE> {											\
    209 	static void constructDefault	(void*)					{}						\
    210 	static void constructCopy		(void* ptr, TYPE val)	{ *(TYPE*)ptr = val; }	\
    211 	static void destruct			(TYPE*)					{}						\
    212 }
    213 
    214 DE_SPECIALIZE_POOL_ARRAY_ELEMENT_BASIC_TYPE(deUint8);
    215 DE_SPECIALIZE_POOL_ARRAY_ELEMENT_BASIC_TYPE(deUint16);
    216 DE_SPECIALIZE_POOL_ARRAY_ELEMENT_BASIC_TYPE(deUint32);
    217 DE_SPECIALIZE_POOL_ARRAY_ELEMENT_BASIC_TYPE(deUint64);
    218 DE_SPECIALIZE_POOL_ARRAY_ELEMENT_BASIC_TYPE(deInt8);
    219 DE_SPECIALIZE_POOL_ARRAY_ELEMENT_BASIC_TYPE(deInt16);
    220 DE_SPECIALIZE_POOL_ARRAY_ELEMENT_BASIC_TYPE(deInt32);
    221 DE_SPECIALIZE_POOL_ARRAY_ELEMENT_BASIC_TYPE(deInt64);
    222 
    223 // PoolArray<T> implementation.
    224 
    225 template<typename T, deUint32 Alignment>
    226 PoolArray<T, Alignment>::PoolArray (MemPool* pool)
    227 	: m_pool				(pool)
    228 	, m_numElements			(0)
    229 	, m_capacity			(0)
    230 	, m_pageTableCapacity	(0)
    231 	, m_pageTable			(0)
    232 {
    233 	DE_ASSERT(deIsPowerOfTwo32(Alignment));
    234 }
    235 
    236 template<typename T, deUint32 Alignment>
    237 PoolArray<T, Alignment>::~PoolArray (void)
    238 {
    239 	// Clear resets values to T()
    240 	clear();
    241 }
    242 
    243 template<typename T, deUint32 Alignment>
    244 inline void PoolArray<T, Alignment>::clear (void)
    245 {
    246 	resize(0);
    247 }
    248 
    249 template<typename T, deUint32 Alignment>
    250 inline void PoolArray<T, Alignment>::resize (deUintptr newSize)
    251 {
    252 	if (newSize < m_numElements)
    253 	{
    254 		// Destruct elements that are no longer active.
    255 		for (deUintptr ndx = newSize; ndx < m_numElements; ndx++)
    256 			PoolArrayElement<T>::destruct(getPtr(ndx));
    257 
    258 		m_numElements = newSize;
    259 	}
    260 	else if (newSize > m_numElements)
    261 	{
    262 		deUintptr prevSize = m_numElements;
    263 
    264 		reserve(newSize);
    265 		m_numElements = newSize;
    266 
    267 		// Fill new elements with default values
    268 		for (deUintptr ndx = prevSize; ndx < m_numElements; ndx++)
    269 			PoolArrayElement<T>::constructDefault(getPtr(ndx));
    270 	}
    271 }
    272 
    273 template<typename T, deUint32 Alignment>
    274 inline void PoolArray<T, Alignment>::resize (deUintptr newSize, const T& value)
    275 {
    276 	if (newSize < m_numElements)
    277 		resize(newSize); // value is not used
    278 	else if (newSize > m_numElements)
    279 	{
    280 		deUintptr prevSize = m_numElements;
    281 
    282 		reserve(newSize);
    283 		m_numElements = newSize;
    284 
    285 		// Fill new elements with copies of value
    286 		for (deUintptr ndx = prevSize; ndx < m_numElements; ndx++)
    287 			PoolArrayElement<T>::constructCopy(getPtr(ndx), value);
    288 	}
    289 }
    290 
    291 template<typename T, deUint32 Alignment>
    292 inline void PoolArray<T, Alignment>::reserve (deUintptr capacity)
    293 {
    294 	if (capacity >= m_capacity)
    295 	{
    296 		void*		oldPageTable			= DE_NULL;
    297 		deUintptr	oldPageTableSize		= 0;
    298 
    299 		deUintptr	newCapacity				= (deUintptr)deAlignPtr((void*)capacity, 1 << ELEMENTS_PER_PAGE_LOG2);
    300 		deUintptr	reqPageTableCapacity	= newCapacity >> ELEMENTS_PER_PAGE_LOG2;
    301 
    302 		if (m_pageTableCapacity < reqPageTableCapacity)
    303 		{
    304 			deUintptr		newPageTableCapacity	= max(2*m_pageTableCapacity, reqPageTableCapacity);
    305 			void**			newPageTable			= (void**)m_pool->alloc(newPageTableCapacity * sizeof(void*));
    306 			deUintptr		i;
    307 
    308 			for (i = 0; i < m_pageTableCapacity; i++)
    309 				newPageTable[i] = m_pageTable[i];
    310 
    311 			for (; i < newPageTableCapacity; i++)
    312 				newPageTable[i] = DE_NULL;
    313 
    314 			// Grab information about old page table for recycling purposes.
    315 			oldPageTable		= m_pageTable;
    316 			oldPageTableSize	= m_pageTableCapacity * sizeof(T*);
    317 
    318 			m_pageTable			= newPageTable;
    319 			m_pageTableCapacity	= newPageTableCapacity;
    320 		}
    321 
    322 		// Allocate new pages.
    323 		{
    324 			deUintptr	elementSize		= (deUintptr)deAlignPtr((void*)(deUintptr)sizeof(T), Alignment);
    325 			deUintptr	pageAllocSize	= elementSize << ELEMENTS_PER_PAGE_LOG2;
    326 			deUintptr	pageTableNdx	= m_capacity >> ELEMENTS_PER_PAGE_LOG2;
    327 
    328 			// Allocate new pages from recycled old page table.
    329 			for (;;)
    330 			{
    331 				void*		newPage			= deAlignPtr(oldPageTable, Alignment);
    332 				deUintptr	alignPadding	= (deUintptr)newPage - (deUintptr)oldPageTable;
    333 
    334 				if (oldPageTableSize < pageAllocSize+alignPadding)
    335 					break; // No free space for alloc + alignment.
    336 
    337 				DE_ASSERT(m_pageTableCapacity > pageTableNdx);
    338 				DE_ASSERT(!m_pageTable[pageTableNdx]);
    339 				m_pageTable[pageTableNdx++] = newPage;
    340 
    341 				oldPageTable		 = (void*)((deUint8*)newPage + pageAllocSize);
    342 				oldPageTableSize	-= pageAllocSize+alignPadding;
    343 			}
    344 
    345 			// Allocate the rest of the needed pages from the pool.
    346 			for (; pageTableNdx < reqPageTableCapacity; pageTableNdx++)
    347 			{
    348 				DE_ASSERT(!m_pageTable[pageTableNdx]);
    349 				m_pageTable[pageTableNdx] = m_pool->alignedAlloc(pageAllocSize, Alignment);
    350 			}
    351 
    352 			m_capacity = pageTableNdx << ELEMENTS_PER_PAGE_LOG2;
    353 			DE_ASSERT(m_capacity >= newCapacity);
    354 		}
    355 	}
    356 }
    357 
    358 template<typename T, deUint32 Alignment>
    359 inline void PoolArray<T, Alignment>::pushBack (const T& value)
    360 {
    361 	resize(size()+1);
    362 	at(size()-1) = value;
    363 }
    364 
    365 template<typename T, deUint32 Alignment>
    366 inline T PoolArray<T, Alignment>::popBack (void)
    367 {
    368 	T val = at(size()-1);
    369 	resize(size()-1);
    370 	return val;
    371 }
    372 
    373 template<typename T, deUint32 Alignment>
    374 inline T* PoolArray<T, Alignment>::getPtr (deIntptr ndx) const
    375 {
    376 	DE_ASSERT(inBounds<deIntptr>(ndx, 0, (deIntptr)m_numElements));
    377 	deUintptr	pageNdx		= ((deUintptr)ndx >> ELEMENTS_PER_PAGE_LOG2);
    378 	deUintptr	subNdx		= (deUintptr)ndx & ((1 << ELEMENTS_PER_PAGE_LOG2) - 1);
    379 	deUintptr	elemSize	= (deUintptr)deAlignPtr((void*)(deUintptr)sizeof(T), Alignment);
    380 	T*			ptr			= (T*)((deUint8*)m_pageTable[pageNdx] + (subNdx*elemSize));
    381 	DE_ASSERT(deIsAlignedPtr(ptr, Alignment));
    382 	return ptr;
    383 }
    384 
    385 // PoolArrayIteratorBase implementation
    386 
    387 template<typename T, deUint32 Alignment>
    388 inline bool operator== (const PoolArrayIteratorBase<T, Alignment>& a, const PoolArrayIteratorBase<T, Alignment>& b)
    389 {
    390 	// \todo [2013-02-08 pyry] Compare array ptr.
    391 	return a.getNdx() == b.getNdx();
    392 }
    393 
    394 template<typename T, deUint32 Alignment>
    395 inline bool operator!= (const PoolArrayIteratorBase<T, Alignment>& a, const PoolArrayIteratorBase<T, Alignment>& b)
    396 {
    397 	// \todo [2013-02-08 pyry] Compare array ptr.
    398 	return a.getNdx() != b.getNdx();
    399 }
    400 
    401 template<typename T, deUint32 Alignment>
    402 inline bool operator< (const PoolArrayIteratorBase<T, Alignment>& a, const PoolArrayIteratorBase<T, Alignment>& b)
    403 {
    404 	return a.getNdx() < b.getNdx();
    405 }
    406 
    407 template<typename T, deUint32 Alignment>
    408 inline bool operator> (const PoolArrayIteratorBase<T, Alignment>& a, const PoolArrayIteratorBase<T, Alignment>& b)
    409 {
    410 	return a.getNdx() > b.getNdx();
    411 }
    412 
    413 template<typename T, deUint32 Alignment>
    414 inline bool operator<= (const PoolArrayIteratorBase<T, Alignment>& a, const PoolArrayIteratorBase<T, Alignment>& b)
    415 {
    416 	return a.getNdx() <= b.getNdx();
    417 }
    418 
    419 template<typename T, deUint32 Alignment>
    420 inline bool operator>= (const PoolArrayIteratorBase<T, Alignment>& a, const PoolArrayIteratorBase<T, Alignment>& b)
    421 {
    422 	return a.getNdx() >= b.getNdx();
    423 }
    424 
    425 // PoolArrayConstIterator<T> implementation
    426 
    427 template<typename T, deUint32 Alignment>
    428 inline PoolArrayConstIterator<T, Alignment>::PoolArrayConstIterator (void)
    429 	: PoolArrayIteratorBase<T, Alignment>	(0)
    430 	, m_array								(DE_NULL)
    431 {
    432 }
    433 
    434 template<typename T, deUint32 Alignment>
    435 inline PoolArrayConstIterator<T, Alignment>::PoolArrayConstIterator (const PoolArray<T, Alignment>* array, deIntptr ndx)
    436 	: PoolArrayIteratorBase<T, Alignment>	(ndx)
    437 	, m_array								(array)
    438 {
    439 }
    440 
    441 template<typename T, deUint32 Alignment>
    442 inline PoolArrayConstIterator<T, Alignment>::PoolArrayConstIterator (const PoolArrayIterator<T, Alignment>& iter)
    443 	: PoolArrayIteratorBase<T, Alignment>	(iter)
    444 	, m_array								(iter.getArray())
    445 {
    446 }
    447 
    448 template<typename T, deUint32 Alignment>
    449 inline PoolArrayConstIterator<T, Alignment>::~PoolArrayConstIterator (void)
    450 {
    451 }
    452 
    453 // Arithmetic operators.
    454 
    455 template<typename T, deUint32 Alignment>
    456 inline PoolArrayConstIterator<T, Alignment> operator+ (const PoolArrayConstIterator<T, Alignment>& iter, deIntptr offs)
    457 {
    458 	return PoolArrayConstIterator<T, Alignment>(iter->getArray(), iter->getNdx()+offs);
    459 }
    460 
    461 template<typename T, deUint32 Alignment>
    462 inline PoolArrayConstIterator<T, Alignment> operator+ (deUintptr offs, const PoolArrayConstIterator<T, Alignment>& iter)
    463 {
    464 	return PoolArrayConstIterator<T, Alignment>(iter->getArray(), iter->getNdx()+offs);
    465 }
    466 
    467 template<typename T, deUint32 Alignment>
    468 PoolArrayConstIterator<T, Alignment> operator- (const PoolArrayConstIterator<T, Alignment>& iter, deIntptr offs)
    469 {
    470 	return PoolArrayConstIterator<T, Alignment>(iter.getArray(), iter.getNdx()-offs);
    471 }
    472 
    473 template<typename T, deUint32 Alignment>
    474 deIntptr operator- (const PoolArrayConstIterator<T, Alignment>& iter, const PoolArrayConstIterator<T, Alignment>& other)
    475 {
    476 	return iter.getNdx()-other.getNdx();
    477 }
    478 
    479 // PoolArrayIterator<T> implementation.
    480 
    481 template<typename T, deUint32 Alignment>
    482 inline PoolArrayIterator<T, Alignment>::PoolArrayIterator (void)
    483 	: PoolArrayIteratorBase<T, Alignment>	(0)
    484 	, m_array								(DE_NULL)
    485 {
    486 }
    487 
    488 template<typename T, deUint32 Alignment>
    489 inline PoolArrayIterator<T, Alignment>::PoolArrayIterator (PoolArray<T, Alignment>* array, deIntptr ndx)
    490 	: PoolArrayIteratorBase<T, Alignment>	(ndx)
    491 	, m_array								(array)
    492 {
    493 }
    494 
    495 template<typename T, deUint32 Alignment>
    496 inline PoolArrayIterator<T, Alignment>::~PoolArrayIterator (void)
    497 {
    498 }
    499 
    500 // Arithmetic operators.
    501 
    502 template<typename T, deUint32 Alignment>
    503 inline PoolArrayIterator<T, Alignment> operator+ (const PoolArrayIterator<T, Alignment>& iter, deIntptr offs)
    504 {
    505 	return PoolArrayIterator<T, Alignment>(iter.getArray(), iter.getNdx()+offs);
    506 }
    507 
    508 template<typename T, deUint32 Alignment>
    509 inline PoolArrayIterator<T, Alignment> operator+ (deUintptr offs, const PoolArrayIterator<T, Alignment>& iter)
    510 {
    511 	return PoolArrayIterator<T, Alignment>(iter.getArray(), iter.getNdx()+offs);
    512 }
    513 
    514 template<typename T, deUint32 Alignment>
    515 PoolArrayIterator<T, Alignment> operator- (const PoolArrayIterator<T, Alignment>& iter, deIntptr offs)
    516 {
    517 	return PoolArrayIterator<T, Alignment>(iter.getArray(), iter.getNdx()-offs);
    518 }
    519 
    520 template<typename T, deUint32 Alignment>
    521 deIntptr operator- (const PoolArrayIterator<T, Alignment>& iter, const PoolArrayIterator<T, Alignment>& other)
    522 {
    523 	return iter.getNdx()-other.getNdx();
    524 }
    525 
    526 } // de
    527 
    528 // std::iterator_traits specializations
    529 namespace std
    530 {
    531 
    532 template<typename T, deUint32 Alignment>
    533 struct iterator_traits<de::PoolArrayConstIterator<T, Alignment> >
    534 {
    535 	typedef deIntptr					difference_type;
    536 	typedef T							value_type;
    537 	typedef const T*					pointer;
    538 	typedef const T&					reference;
    539 	typedef random_access_iterator_tag	iterator_category;
    540 };
    541 
    542 template<typename T, deUint32 Alignment>
    543 struct iterator_traits<de::PoolArrayIterator<T, Alignment> >
    544 {
    545 	typedef deIntptr					difference_type;
    546 	typedef T							value_type;
    547 	typedef T*							pointer;
    548 	typedef T&							reference;
    549 	typedef random_access_iterator_tag	iterator_category;
    550 };
    551 
    552 } // std
    553 
    554 #endif // _DEPOOLARRAY_HPP
    555