diff --git a/src/libCom/cxxTemplates/tsFreeList.h b/src/libCom/cxxTemplates/tsFreeList.h new file mode 100644 index 000000000..145d98301 --- /dev/null +++ b/src/libCom/cxxTemplates/tsFreeList.h @@ -0,0 +1,121 @@ + +/* $Id$ + * + * L O S A L A M O S + * Los Alamos National Laboratory + * Los Alamos, New Mexico 87545 + * + * Copyright, 1986, The Regents of the University of California. + * + * Author: Jeff Hill + */ + +#include "osiMutex.h" + +#if defined(_MSC_VER) && _MSC_VER <= 1200 +# pragma warning( disable : 4291 ) +#endif + +template < class T > +class tsFreeListItem { +public: + union { + tsFreeListItem < T > *pNext; + char pad[ sizeof (T) ]; + }; +}; + +template < class T, unsigned N = 0x400 > +class tsFreeListChunk { +public: + tsFreeListChunk < T, N > *pNext; + tsFreeListItem < T > items [N]; +}; + +template < class T, unsigned N > +class tsFreeList : private osiMutex { +public: + tsFreeList (); + ~tsFreeList (); + void * allocate ( size_t size ); + void release ( void *p, size_t size ); +private: + tsFreeListItem < T > *pFreeList; + tsFreeListChunk < T, N > *pChunkList; +}; + +template < class T, unsigned N > +inline tsFreeList < T, N >::tsFreeList () : + pFreeList (0), pChunkList (0) {} + +template < class T, unsigned N > +tsFreeList < T, N >::~tsFreeList () +{ + tsFreeListChunk < T, N > *pChunk; + + this->lock (); + + while ( ( pChunk = this->pChunkList ) ) { + this->pChunkList = this->pChunkList->pNext; + delete pChunk; + } + + this->unlock(); +} + +template < class T, unsigned N > +void * tsFreeList < T, N >::allocate (size_t size) +{ + tsFreeListItem < T > *p; + + if (size != sizeof (*p) ) { + return ::operator new (size); + } + + this->lock (); + + p = this->pFreeList; + + if ( p ) { + this->pFreeList = p->pNext; + } + else { + unsigned i; + + tsFreeListChunk *pChunk = new ( tsFreeListChunk < T, N > ); + if ( ! pChunk) { + return 0; + } + + for ( i=1u; i < N-1; i++ ) { + pChunk->items[i].pNext = &pChunk->items[i+1]; + } + pChunk->items[N-1].pNext = 0; + p = &pChunk->items[0]; + this->pFreeList = &pChunk->items[1u]; + pChunk->pNext = this->pChunkList; + this->pChunkList = pChunk; + } + + this->unlock (); + + return static_cast (p); +} + +template < class T, unsigned N > +void tsFreeList < T, N >::release (void *pCadaver, size_t size) +{ + if ( size != sizeof (tsFreeListItem) ) { + ::operator delete (pCadaver); + } + else { + if ( pCadaver ) { + this->lock (); + tsFreeListItem *p = + static_cast < tsFreeListItem < T > *> (pCadaver); + p->pNext = this->pFreeList; + this->pFreeList = p; + this->unlock (); + } + } +}