From c18a9fb345a2f05cfa83b063fd0b41ab3382b268 Mon Sep 17 00:00:00 2001 From: Jeff Hill Date: Thu, 21 Mar 2002 22:15:57 +0000 Subject: [PATCH] simplified --- src/libCom/cxxTemplates/tsFreeList.h | 142 ++++++++++++++------------- 1 file changed, 72 insertions(+), 70 deletions(-) diff --git a/src/libCom/cxxTemplates/tsFreeList.h b/src/libCom/cxxTemplates/tsFreeList.h index 89bff2962..402214992 100644 --- a/src/libCom/cxxTemplates/tsFreeList.h +++ b/src/libCom/cxxTemplates/tsFreeList.h @@ -26,39 +26,41 @@ // 1) add the following static, private free list data members // to your class // -// static tsFreeList < class classXYZ, 1024 > freeList; -// static epicsMutex freeListMutex; +// static epicsSingleton < tsFreeList < class classXYZ > > pFreeList; // // 2) add the following member functions to your class // // inline void * classXYZ::operator new ( size_t size ) // { -// epicsAutoMutex locker ( classXYZ::freeListMutex ); -// void *p = classXYZ::freeList.allocate ( size ); -// if ( ! p ) { -// throw std::bad_alloc (); -// } -// return p; +// return classXYZ::pFreeList->allocate ( size ); // } // // inline void classXYZ::operator delete ( void *pCadaver, size_t size ) // { -// epicsAutoMutex locker ( classXYZ::freeListMutex ); -// classXYZ::freeList.release ( pCadaver, size ); +// classXYZ::pFreeList->release ( pCadaver, size ); // } // // NOTES: // -// 1) If a tsFreeList instance is used by more than one thread then the -// user must provide mutual exclusion in their new and delete handlers. +// 1) A NOOP mutex class may be specified if mutual exclusion isnt required // // 2) If you wish to force use of the new operator, then declare your class's // destructor as a protected member function. // +// 3) Setting N to zero causes the free list to be bypassed +// #include +#include #include #include "epicsMutex.h" +#include "epicsGuard.h" + +#ifdef EPICS_FREELIST_DEBUG + static const bool tsFreeListDebugBypass = true; +#else + static const bool tsFreeListDebugBypass = false; +#endif // these versions of the microsoft compiler incorrectly // warn about a missing delete operator if only the @@ -74,7 +76,8 @@ template < class T, unsigned DEBUG_LEVEL > template < class T, unsigned N, unsigned DEBUG_LEVEL> struct tsFreeListChunk; -template < class T, unsigned N = 0x400, unsigned DEBUG_LEVEL = 0u > +template < class T, unsigned N = 0x400, + class MUTEX = epicsMutex, unsigned DEBUG_LEVEL = 0u > class tsFreeList { public: tsFreeList (); @@ -84,13 +87,14 @@ public: private: tsFreeListItem < T, DEBUG_LEVEL > *pFreeList; tsFreeListChunk < T, N, DEBUG_LEVEL > *pChunkList; + MUTEX mutex; tsFreeListItem < T, DEBUG_LEVEL > * allocateFromNewChunk (); }; template < class T, unsigned DEBUG_LEVEL > union tsFreeListItem { public: - char pad[ sizeof ( T ) ]; + char pad [ sizeof ( T ) ]; tsFreeListItem < T, DEBUG_LEVEL > *pNext; }; @@ -100,76 +104,74 @@ struct tsFreeListChunk { tsFreeListChunk < T, N, DEBUG_LEVEL > *pNext; }; -template < class T, unsigned N, unsigned DEBUG_LEVEL > -inline tsFreeList < T, N, DEBUG_LEVEL > :: tsFreeList () : +template < class T, unsigned N, class MUTEX, unsigned DEBUG_LEVEL > +inline tsFreeList < T, N, MUTEX, DEBUG_LEVEL > :: tsFreeList () : pFreeList ( 0 ), pChunkList ( 0 ) {} -template < class T, unsigned N, unsigned DEBUG_LEVEL > -tsFreeList < T, N, DEBUG_LEVEL > :: ~tsFreeList () +template < class T, unsigned N, class MUTEX, unsigned DEBUG_LEVEL > +tsFreeList < T, N, MUTEX, DEBUG_LEVEL > :: ~tsFreeList () { tsFreeListChunk < T, N, DEBUG_LEVEL > *pChunk; unsigned nChunks; - if ( DEBUG_LEVEL > 0u ) { + if ( DEBUG_LEVEL > 1u ) { nChunks = 0u; } while ( ( pChunk = this->pChunkList ) ) { this->pChunkList = this->pChunkList->pNext; delete pChunk; - if ( DEBUG_LEVEL > 0u ) { + if ( DEBUG_LEVEL > 1u ) { nChunks++; } } - if ( DEBUG_LEVEL > 0u ) { + if ( DEBUG_LEVEL > 1u ) { fprintf ( stderr, "free list destructor for class %s returned %u objects to pool\n", typeid ( T ).name (), N * nChunks ); } } -template < class T, unsigned N, unsigned DEBUG_LEVEL > -inline void * tsFreeList < T, N, DEBUG_LEVEL >::allocate ( size_t size ) +template < class T, unsigned N, class MUTEX, unsigned DEBUG_LEVEL > +void * tsFreeList < T, N, MUTEX, DEBUG_LEVEL >::allocate ( size_t size ) { -# ifdef EPICS_FREELIST_DEBUG - return ::operator new ( size, std::nothrow ); -# else - tsFreeListItem < T, DEBUG_LEVEL > *p; + if ( DEBUG_LEVEL > 1 ) { + fprintf ( stderr, "creating a new %s of size %u\n", + typeid ( T ).name (), sizeof ( T ) ); + } - if ( DEBUG_LEVEL > 9 ) { - fprintf ( stderr, "creating a new %s of size %u\n", - typeid ( T ).name (), sizeof ( T ) ); + if ( size != sizeof ( T ) || N == 0u || tsFreeListDebugBypass ) { + void *p = ::operator new ( size, std::nothrow ); + if ( ! p ) { + throw std::bad_alloc (); } + if ( tsFreeListDebugBypass ) { + memset ( p, 0xaa, size ); + } + return p; + } - if ( size != sizeof ( T ) || N == 0u ) { - return ::operator new ( size, std::nothrow ); - } + epicsGuard < MUTEX > guard ( this->mutex ); - p = this->pFreeList; - if ( p ) { - this->pFreeList = p->pNext; - } - else { - p = this->allocateFromNewChunk (); - } + tsFreeListItem < T, DEBUG_LEVEL > *p = this->pFreeList; + if ( p ) { + this->pFreeList = p->pNext; + } + else { + p = this->allocateFromNewChunk (); + } - return static_cast < void * > ( p ); -# endif + return static_cast < void * > ( p ); } -template < class T, unsigned N, unsigned DEBUG_LEVEL > -tsFreeListItem < T, DEBUG_LEVEL > * tsFreeList < T, N, DEBUG_LEVEL >::allocateFromNewChunk () +template < class T, unsigned N, class MUTEX, unsigned DEBUG_LEVEL > +tsFreeListItem < T, DEBUG_LEVEL > * + tsFreeList < T, N, MUTEX, DEBUG_LEVEL >::allocateFromNewChunk () { - //if ( DEBUG_LEVEL > 0 ) { - // fprintf ( stderr, "allocating a %s of size %u\n", - // typeid ( tsFreeListChunk < T, N, DEBUG_LEVEL > ).name (), - // sizeof ( tsFreeListChunk < T, N, DEBUG_LEVEL > ) ); - //} - tsFreeListChunk < T, N, DEBUG_LEVEL > *pChunk = new ( std::nothrow ) ( tsFreeListChunk < T, N, DEBUG_LEVEL > ); if ( ! pChunk ) { - return 0; + throw std::bad_alloc (); } for ( unsigned i=1u; i < N-1; i++ ) { @@ -185,27 +187,27 @@ tsFreeListItem < T, DEBUG_LEVEL > * tsFreeList < T, N, DEBUG_LEVEL >::allocateFr return &pChunk->items[0]; } -template < class T, unsigned N, unsigned DEBUG_LEVEL > -inline void tsFreeList < T, N, DEBUG_LEVEL >::release ( void *pCadaver, size_t size ) +template < class T, unsigned N, class MUTEX, unsigned DEBUG_LEVEL > +void tsFreeList < T, N, MUTEX, DEBUG_LEVEL >::release + ( void *pCadaver, size_t size ) { -# ifdef EPICS_FREELIST_DEBUG - memset ( pCadaver, 0xdd, size ); + if ( DEBUG_LEVEL > 1 ) { + fprintf ( stderr, "releasing a %s of size %u\n", + typeid ( T ).name (), sizeof ( T ) ); + } + if ( size != sizeof ( T ) || N == 0u || tsFreeListDebugBypass ) { + if ( tsFreeListDebugBypass ) { + memset ( pCadaver, 0xdd, size ); + } ::operator delete ( pCadaver ); -# else - if ( DEBUG_LEVEL > 9 ) { - fprintf ( stderr, "releasing a %s of size %u\n", - typeid ( T ).name (), sizeof ( T ) ); - } - if ( size != sizeof ( T ) || N == 0u ) { - ::operator delete ( pCadaver ); - } - else if ( pCadaver ) { - tsFreeListItem < T, DEBUG_LEVEL > *p = - static_cast < tsFreeListItem < T, DEBUG_LEVEL > *> ( pCadaver ); - p->pNext = this->pFreeList; - this->pFreeList = p; - } -# endif + } + else if ( pCadaver ) { + epicsGuard < MUTEX > guard ( this->mutex ); + tsFreeListItem < T, DEBUG_LEVEL > *p = + static_cast < tsFreeListItem < T, DEBUG_LEVEL > *> ( pCadaver ); + p->pNext = this->pFreeList; + this->pFreeList = p; + } } #endif // tsFreeList_h