fsa.h
Go to the documentation of this file.
00001 /* 
00002 
00003 A* Algorithm Implementation using STL is
00004 Copyright (C)2001-2005 Justin Heyes-Jones
00005 
00006 Permission is given by the author to freely redistribute and 
00007 include this code in any program as long as this credit is 
00008 given where due.
00009  
00010   COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, 
00011   WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, 
00012   INCLUDING, WITHOUT LIMITATION, WARRANTIES THAT THE COVERED CODE 
00013   IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
00014   OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND 
00015   PERFORMANCE OF THE COVERED CODE IS WITH YOU. SHOULD ANY COVERED 
00016   CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT THE INITIAL 
00017   DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY 
00018   NECESSARY SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF 
00019   WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS LICENSE. NO USE 
00020   OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
00021   THIS DISCLAIMER.
00022  
00023   Use at your own risk!
00024 
00025 
00026 
00027   FixedSizeAllocator class
00028   Copyright 2001 Justin Heyes-Jones
00029 
00030   This class is a constant time O(1) memory manager for objects of 
00031   a specified type. The type is specified using a template class.
00032 
00033   Memory is allocated from a fixed size buffer which you can specify in the
00034   class constructor or use the default.
00035 
00036   Using GetFirst and GetNext it is possible to iterate through the elements
00037   one by one, and this would be the most common use for the class. 
00038 
00039   I would suggest using this class when you want O(1) add and delete
00040   and you don't do much searching, which would be O(n). Structures such as binary 
00041   trees can be used instead to get O(logn) access time.
00042 
00043 */
00044 
00045 #ifndef FSA_H
00046 #define FSA_H
00047 
00048 #include <string.h>
00049 #include <stdio.h>
00050 
00051 template <class USER_TYPE> class FixedSizeAllocator
00052 {
00053 
00054 public: 
00055         // Constants
00056         enum
00057         {
00058                 FSA_DEFAULT_SIZE = 100
00059         };
00060 
00061         // This class enables us to transparently manage the extra data 
00062         // needed to enable the user class to form part of the double-linked
00063         // list class
00064         struct FSA_ELEMENT
00065         {
00066                 USER_TYPE UserType;
00067                 
00068                 FSA_ELEMENT *pPrev;
00069                 FSA_ELEMENT *pNext;
00070         };
00071 
00072 public: // methods
00073         FixedSizeAllocator( unsigned int MaxElements = FSA_DEFAULT_SIZE ) :
00074         m_MaxElements( MaxElements ),
00075         m_pFirstUsed( NULL )
00076         {
00077                 // Allocate enough memory for the maximum number of elements
00078 
00079                 m_pMemory = (FSA_ELEMENT *) (new char[ m_MaxElements * sizeof(FSA_ELEMENT) ]); 
00080 
00081                 // Set the free list first pointer
00082                 m_pFirstFree = m_pMemory;
00083 
00084                 // Clear the memory
00085                 memset( m_pMemory, 0, sizeof( FSA_ELEMENT ) * m_MaxElements );
00086 
00087                 // Point at first element
00088                 FSA_ELEMENT *pElement = m_pFirstFree;
00089 
00090                 // Set the double linked free list
00091                 for( unsigned int i=0; i<m_MaxElements; i++ )
00092                 {
00093                         pElement->pPrev = pElement-1;
00094                         pElement->pNext = pElement+1;
00095 
00096                         pElement++;
00097                 }
00098 
00099                 // first element should have a null prev
00100                 m_pFirstFree->pPrev = NULL;
00101                 // last element should have a null next
00102                 (pElement-1)->pNext = NULL;
00103 
00104         }
00105 
00106 
00107         ~FixedSizeAllocator()
00108         {
00109                 // Free up the memory
00110                 delete [] (char *) m_pMemory;
00111         }
00112 
00113         // Allocate a new USER_TYPE and return a pointer to it 
00114         USER_TYPE *alloc()
00115         {
00116 
00117                 FSA_ELEMENT *pNewNode = NULL;
00118 
00119                 if( !m_pFirstFree )
00120                 {
00121                         return NULL;
00122                 }
00123                 else
00124                 {
00125                         pNewNode = m_pFirstFree;
00126                         m_pFirstFree = pNewNode->pNext;
00127 
00128                         // if the new node points to another free node then
00129                         // change that nodes prev free pointer...
00130                         if( pNewNode->pNext )
00131                         {
00132                                 pNewNode->pNext->pPrev = NULL;
00133                         }
00134 
00135                         // node is now on the used list
00136 
00137                         pNewNode->pPrev = NULL; // the allocated node is always first in the list
00138 
00139                         if( m_pFirstUsed == NULL )
00140                         {
00141                                 pNewNode->pNext = NULL; // no other nodes
00142                         }
00143                         else
00144                         {
00145                                 m_pFirstUsed->pPrev = pNewNode; // insert this at the head of the used list
00146                                 pNewNode->pNext = m_pFirstUsed;
00147                         }
00148 
00149                         m_pFirstUsed = pNewNode;
00150                 }       
00151                 
00152                 return reinterpret_cast<USER_TYPE*>(pNewNode);
00153         }
00154 
00155         // Free the given user type
00156         // For efficiency I don't check whether the user_data is a valid
00157         // pointer that was allocated. I may add some debug only checking
00158         // (To add the debug check you'd need to make sure the pointer is in 
00159         // the m_pMemory area and is pointing at the start of a node)
00160         void free( USER_TYPE *user_data )
00161         {
00162                 FSA_ELEMENT *pNode = reinterpret_cast<FSA_ELEMENT*>(user_data);
00163 
00164                 // manage used list, remove this node from it
00165                 if( pNode->pPrev )
00166                 {
00167                         pNode->pPrev->pNext = pNode->pNext;
00168                 }
00169                 else
00170                 {
00171                         // this handles the case that we delete the first node in the used list
00172                         m_pFirstUsed = pNode->pNext;
00173                 }
00174 
00175                 if( pNode->pNext )
00176                 {
00177                         pNode->pNext->pPrev = pNode->pPrev;
00178                 }
00179 
00180                 // add to free list
00181                 if( m_pFirstFree == NULL ) 
00182                 {
00183                         // free list was empty
00184                         m_pFirstFree = pNode;
00185                         pNode->pPrev = NULL;
00186                         pNode->pNext = NULL;
00187                 }
00188                 else
00189                 {
00190                         // Add this node at the start of the free list
00191                         m_pFirstFree->pPrev = pNode;
00192                         pNode->pNext = m_pFirstFree;
00193                         m_pFirstFree = pNode;
00194                 }
00195 
00196         }
00197 
00198         // For debugging this displays both lists (using the prev/next list pointers)
00199         void Debug()
00200         {
00201                 printf( "free list " );
00202 
00203                 FSA_ELEMENT *p = m_pFirstFree;
00204                 while( p )
00205                 {
00206                         printf( "%x!%x ", p->pPrev, p->pNext );
00207                         p = p->pNext;
00208                 }
00209                 printf( "\n" );
00210 
00211                 printf( "used list " );
00212 
00213                 p = m_pFirstUsed;
00214                 while( p )
00215                 {
00216                         printf( "%x!%x ", p->pPrev, p->pNext );
00217                         p = p->pNext;
00218                 }
00219                 printf( "\n" );
00220         }
00221 
00222         // Iterators
00223 
00224         USER_TYPE *GetFirst()
00225         {
00226                 return reinterpret_cast<USER_TYPE *>(m_pFirstUsed);
00227         }
00228 
00229         USER_TYPE *GetNext( USER_TYPE *node )
00230         {
00231                 return reinterpret_cast<USER_TYPE *>
00232                         (
00233                                 (reinterpret_cast<FSA_ELEMENT *>(node))->pNext
00234                         );
00235         }
00236 
00237 public: // data
00238 
00239 private: // methods
00240 
00241 private: // data
00242 
00243         FSA_ELEMENT *m_pFirstFree;
00244         FSA_ELEMENT *m_pFirstUsed;
00245         unsigned int m_MaxElements;
00246         FSA_ELEMENT *m_pMemory;
00247 
00248 };
00249 
00250 #endif // defined FSA_H


stage
Author(s): Richard Vaughan , Brian Gerkey , Reed Hedges , Andrew Howard , Toby Collett , Pooya Karimian , Jeremy Asher , Alex Couture-Beil , Geoff Biggs , Rich Mattes , Abbas Sadat
autogenerated on Thu Aug 27 2015 15:20:57