simplified

This commit is contained in:
Jeff Hill
2002-03-21 22:15:57 +00:00
parent 46037c48cb
commit c18a9fb345

View File

@@ -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 <stdio.h>
#include <string.h>
#include <typeinfo>
#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