283 lines
8.7 KiB
C++
283 lines
8.7 KiB
C++
#ifndef _TLC_HPP_
|
|
#define _TLC_HPP_
|
|
// Ruler
|
|
// 1 2 3 4 5 6 7 8
|
|
//345678901234567890123456789012345678901234567890123456789012345678901234567890
|
|
|
|
/********************************************************************/
|
|
/* */
|
|
/* The standard layout. */
|
|
/* */
|
|
/* The standard layout for 'hpp' files for this code is as */
|
|
/* follows: */
|
|
/* */
|
|
/* 1. Include files. */
|
|
/* 2. Constants exported from the class. */
|
|
/* 3. Data structures exported from the class. */
|
|
/* 4. Forward references to other data structures. */
|
|
/* 5. Class specifications (including inline functions). */
|
|
/* 6. Additional large inline functions. */
|
|
/* */
|
|
/* Any portion that is not required is simply omitted. */
|
|
/* */
|
|
/********************************************************************/
|
|
|
|
#include "Global.hpp"
|
|
|
|
#include "List.hpp"
|
|
#include "Spinlock.hpp"
|
|
#include "Tls.hpp"
|
|
|
|
/********************************************************************/
|
|
/* */
|
|
/* A thread local class. */
|
|
/* */
|
|
/* A significant number of SMP applications need thread local */
|
|
/* data structures. Here we support the automatic creation */
|
|
/* and management of such structures. */
|
|
/* */
|
|
/********************************************************************/
|
|
|
|
template <class TYPE> class TLC
|
|
{
|
|
//
|
|
// Private data.
|
|
//
|
|
LIST ActiveList;
|
|
LIST FreeList;
|
|
SPINLOCK Spinlock;
|
|
TLS Tls;
|
|
|
|
public:
|
|
//
|
|
// Public functions.
|
|
//
|
|
TLC( VOID );
|
|
|
|
~TLC( VOID );
|
|
|
|
//
|
|
// Public inline functions.
|
|
//
|
|
INLINE TYPE *GetPointer( VOID )
|
|
{
|
|
REGISTER LIST *Class = ((LIST*) Tls.GetPointer());
|
|
|
|
return ((Class != NULL) ? ((TYPE*) & Class[1]) : CreateClass());
|
|
}
|
|
|
|
INLINE VOID Delete( VOID )
|
|
{
|
|
REGISTER LIST *Class = ((LIST*) Tls.GetPointer());
|
|
|
|
if ( Class != NULL )
|
|
{ DeleteClass( Class ); }
|
|
}
|
|
|
|
private:
|
|
//
|
|
// Private functions.
|
|
//
|
|
TYPE *CreateClass( VOID );
|
|
|
|
VOID DeleteClass( LIST *Class );
|
|
|
|
//
|
|
// Disabled operations.
|
|
//
|
|
TLC( CONST TLC & Copy );
|
|
|
|
VOID operator=( CONST TLC & Copy );
|
|
};
|
|
#endif
|
|
|
|
/********************************************************************/
|
|
/* */
|
|
/* Class constructor. */
|
|
/* */
|
|
/* Create a thread private management class. This call is */
|
|
/* not thread safe and should only be made in a single thread */
|
|
/* environment. */
|
|
/* */
|
|
/********************************************************************/
|
|
|
|
template <class TYPE> TLC<TYPE>::TLC( VOID )
|
|
{ /* void */ }
|
|
|
|
/********************************************************************/
|
|
/* */
|
|
/* Create a new class. */
|
|
/* */
|
|
/* Create a new private class and store a pointer to it in */
|
|
/* the thread local store. */
|
|
/* */
|
|
/********************************************************************/
|
|
|
|
template <class TYPE> TYPE *TLC<TYPE>::CreateClass( VOID )
|
|
{
|
|
REGISTER LIST *Class;
|
|
|
|
//
|
|
// Claim a spinlock just in case multiple
|
|
// threads are active.
|
|
//
|
|
Spinlock.ClaimLock();
|
|
|
|
//
|
|
// We are more than happy to use any existing
|
|
// memory allocation from the free list if
|
|
// one is available.
|
|
//
|
|
Class = FreeList.First();
|
|
|
|
//
|
|
// If the free list is empty we create a new
|
|
// class using the memory allocator. If it is
|
|
// not empty we delete the first element from
|
|
// the list.
|
|
//
|
|
if ( Class == NULL )
|
|
{
|
|
REGISTER SBIT32 TotalSize = (sizeof(LIST) + sizeof(TYPE));
|
|
|
|
//
|
|
// Cache align the size. This may look
|
|
// like a waste of time but is worth
|
|
// 30% in some cases when we are correctly
|
|
// aligned.
|
|
//
|
|
TotalSize = ((TotalSize + CacheLineMask) & ~CacheLineMask);
|
|
|
|
Class = ((LIST*) new CHAR [ TotalSize ]);
|
|
}
|
|
else
|
|
{ Class -> Delete( & FreeList ); }
|
|
|
|
PLACEMENT_NEW( & Class[0],LIST );
|
|
|
|
//
|
|
// We need to add the new class to the active
|
|
// list so we can rememebr to delete it later.
|
|
//
|
|
Class -> Insert( & ActiveList );
|
|
|
|
//
|
|
// Relaese the lock we claimed earlier.
|
|
//
|
|
Spinlock.ReleaseLock();
|
|
|
|
//
|
|
// Finally, update the TLS pointer and call the
|
|
// class constructor to get everything ready for
|
|
// use.
|
|
//
|
|
Tls.SetPointer( Class );
|
|
|
|
PLACEMENT_NEW( & Class[1],TYPE );
|
|
|
|
return ((TYPE*) & Class[1]);
|
|
}
|
|
|
|
/********************************************************************/
|
|
/* */
|
|
/* Delete a class. */
|
|
/* */
|
|
/* We may need to delete a thread local class in some situations */
|
|
/* so here we call the destructor and recycle the memory. */
|
|
/* */
|
|
/********************************************************************/
|
|
|
|
template <class TYPE> VOID TLC<TYPE>::DeleteClass( LIST *Class )
|
|
{
|
|
//
|
|
// Call the destructor for clean up.
|
|
//
|
|
PLACEMENT_DELETE( & Class[1],TYPE );
|
|
|
|
//
|
|
// Claim a spinlock just in case multiple
|
|
// threads are active.
|
|
//
|
|
Spinlock.Claimlock();
|
|
|
|
//
|
|
// Call the destructor for clean up.
|
|
//
|
|
PLACEMENT_DELETE( & Class[0],LIST );
|
|
|
|
//
|
|
// Move the element from the active list
|
|
// to the free list.
|
|
//
|
|
Class -> Delete( & ActiveList );
|
|
|
|
Class -> Insert( & FreeList );
|
|
|
|
//
|
|
// Relaese the lock we claimed earlier.
|
|
//
|
|
Spinlock.ReleaseLock();
|
|
|
|
//
|
|
// Finally, zero the TLS pointer.
|
|
//
|
|
Tls.SetPointer( NULL );
|
|
}
|
|
|
|
/********************************************************************/
|
|
/* */
|
|
/* Class destructor. */
|
|
/* */
|
|
/* Destroy a thread private management class. This call is */
|
|
/* not thread safe and should only be made in a single thread */
|
|
/* environment. */
|
|
/* */
|
|
/********************************************************************/
|
|
|
|
template <class TYPE> TLC<TYPE>::~TLC( VOID )
|
|
{
|
|
REGISTER LIST *Current;
|
|
|
|
//
|
|
// Walk the list of active classes and release
|
|
// them back to the heap.
|
|
//
|
|
for
|
|
(
|
|
Current = ActiveList.First();
|
|
Current != NULL;
|
|
Current = ActiveList.First()
|
|
)
|
|
{
|
|
//
|
|
// Call the destructor, remove the element
|
|
// from the active list and free it.
|
|
//
|
|
PLACEMENT_DELETE( (Current + 1),TYPE );
|
|
|
|
Current -> Delete( & ActiveList );
|
|
|
|
delete [] ((CHAR*) Current);
|
|
}
|
|
|
|
//
|
|
// Walk the list of free classes and release
|
|
// them back to the heap.
|
|
//
|
|
for
|
|
(
|
|
Current = FreeList.First();
|
|
Current != NULL;
|
|
Current = FreeList.First()
|
|
)
|
|
{
|
|
//
|
|
// Remove the element from the free list
|
|
// and free it.
|
|
//
|
|
Current -> Delete( & FreeList );
|
|
|
|
delete [] Current;
|
|
}
|
|
}
|