/[pcsx2_0.9.7]/trunk/common/include/Utilities/SafeArray.h
ViewVC logotype

Diff of /trunk/common/include/Utilities/SafeArray.h

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 31 by william, Tue Sep 7 03:24:11 2010 UTC revision 62 by william, Tue Sep 7 11:08:22 2010 UTC
# Line 15  Line 15 
15    
16  #pragma once  #pragma once
17    
 #include "MemcpyFast.h"  
   
 extern void* __fastcall pcsx2_aligned_malloc(size_t size, size_t align);  
 extern void* __fastcall pcsx2_aligned_realloc(void* handle, size_t size, size_t align);  
 extern void pcsx2_aligned_free(void* pmem);  
   
 // aligned_malloc: Implement/declare linux equivalents here!  
 #if !defined(_MSC_VER) && !defined(HAVE_ALIGNED_MALLOC)  
 #       define _aligned_malloc pcsx2_aligned_malloc  
 #       define _aligned_free pcsx2_aligned_free  
 #       define _aligned_realloc pcsx2_aligned_realloc  
 #endif  
18    
19  //////////////////////////////////////////////////////////////////////////////////////////  //////////////////////////////////////////////////////////////////////////////////////////
20  // Safe deallocation macros -- checks pointer validity (non-null) when needed, and sets  // Safe deallocation macros -- checks pointer validity (non-null) when needed, and sets
# Line 60  extern void pcsx2_aligned_free(void* pme Line 48  extern void pcsx2_aligned_free(void* pme
48  #define safe_release( ptr ) \  #define safe_release( ptr ) \
49          ((void) (( ( (ptr) != NULL ) && ((ptr)->Release(), !!0) ), (ptr) = NULL))          ((void) (( ( (ptr) != NULL ) && ((ptr)->Release(), !!0) ), (ptr) = NULL))
50    
51  //////////////////////////////////////////////////////////////////////////////////////////  // --------------------------------------------------------------------------------------
52  // Handy little class for allocating a resizable memory block, complete with  //  SafeArray
53  // exception-based error handling and automatic cleanup.  // --------------------------------------------------------------------------------------
54    // Handy little class for allocating a resizable memory block, complete with exception
55    // error handling and automatic cleanup.  A lightweight alternative to std::vector.
56  //  //
57  template< typename T >  template< typename T >
58  class SafeArray  class SafeArray
# Line 77  public: Line 67  public:
67          int                     ChunkSize;          int                     ChunkSize;
68    
69  protected:  protected:
70          T*              m_ptr;          T*                      m_ptr;
71          int             m_size;                         // size of the allocation of memory          int                     m_size;                 // size of the allocation of memory
72    
73  protected:  protected:
74          // Internal constructor for use by derived classes.  This allows a derived class to          SafeArray( const wxChar* name, T* allocated_mem, int initSize );
75          // use its own memory allocation (with an aligned memory, for example).          virtual T* _virtual_realloc( int newsize );
         // Throws:  
         //   Exception::OutOfMemory if the allocated_mem pointer is NULL.  
         explicit SafeArray( const wxChar* name, T* allocated_mem, int initSize )  
                 : Name( name )  
         {  
                 ChunkSize       = DefaultChunkSize;  
                 m_ptr           = allocated_mem;  
                 m_size          = initSize;  
   
                 if( m_ptr == NULL )  
                         throw Exception::OutOfMemory();  
         }  
76    
77          virtual T* _virtual_realloc( int newsize )          // A safe array index fetcher.  Asserts if the index is out of bounds (dev and debug
78            // builds only -- no bounds checking is done in release builds).
79            T* _getPtr( uint i ) const
80          {          {
81                  return (T*)((m_ptr == NULL) ?                  IndexBoundsAssumeDev( Name.c_str(), i, m_size );
82                          malloc( newsize * sizeof(T) ) :                  return &m_ptr[i];
                         realloc( m_ptr, newsize * sizeof(T) )  
                 );  
83          }          }
84    
85  public:  public:
86          virtual ~SafeArray()          virtual ~SafeArray() throw();
         {  
                 safe_free( m_ptr );  
         }  
   
         explicit SafeArray( const wxChar* name=L"Unnamed" )  
                 : Name( name )  
         {  
                 ChunkSize       = DefaultChunkSize;  
                 m_ptr           = NULL;  
                 m_size          = 0;  
         }  
   
         explicit SafeArray( int initialSize, const wxChar* name=L"Unnamed" )  
                 : Name( name )  
         {  
                 ChunkSize       = DefaultChunkSize;  
                 m_ptr           = (initialSize==0) ? NULL : (T*)malloc( initialSize * sizeof(T) );  
                 m_size          = initialSize;  
87    
88                  if( (initialSize != 0) && (m_ptr == NULL) )          explicit SafeArray( const wxChar* name=L"Unnamed" );
89                          throw Exception::OutOfMemory();          explicit SafeArray( int initialSize, const wxChar* name=L"Unnamed" );
90          }          
91            void Dispose();
92          // Clears the contents of the array to zero, and frees all memory allocations.          void ExactAlloc( int newsize );
93          void Dispose()          void MakeRoomFor( int newsize )
94          {          {
95                  m_size = 0;                  if( newsize > m_size )
96                  safe_free( m_ptr );                          ExactAlloc( newsize );
97          }          }
98    
99          bool IsDisposed() const { return (m_ptr==NULL); }          bool IsDisposed() const { return (m_ptr==NULL); }
# Line 143  public: Line 103  public:
103          // Returns the size of the memory allocation in bytes.          // Returns the size of the memory allocation in bytes.
104          int GetSizeInBytes() const { return m_size * sizeof(T); }          int GetSizeInBytes() const { return m_size * sizeof(T); }
105    
         // reallocates the array to the explicit size.  Can be used to shrink or grow an  
         // array, and bypasses the internal threshold growth indicators.  
         void ExactAlloc( int newsize )  
         {  
                 if( newsize == m_size ) return;  
   
                 m_ptr = _virtual_realloc( newsize );  
                 if( m_ptr == NULL )  
                 {  
                         throw Exception::OutOfMemory(  
                                 wxsFormat(      // english (for diagnostic)  
                                         L"Out-of-memory on SafeArray block re-allocation.\n"  
                                         L"Old size: %d bytes, New size: %d bytes.",  
                                         m_size, newsize  
                                 ),  
                                 // internationalized!  
                                 wxsFormat( _("Out of memory, trying to allocate %d bytes."), newsize )  
                         );  
                 }  
                 m_size = newsize;  
         }  
   
         // Ensures that the allocation is large enough to fit data of the  
         // amount requested.  The memory allocation is not resized smaller.  
         void MakeRoomFor( int newsize )  
         {  
                 if( newsize > m_size )  
                         ExactAlloc( newsize );  
         }  
   
106          // Extends the containment area of the array.  Extensions are performed          // Extends the containment area of the array.  Extensions are performed
107          // in chunks.          // in chunks.
108          void GrowBy( int items )          void GrowBy( int items )
# Line 190  public: Line 120  public:
120          T& operator[]( int idx ) { return *_getPtr( (uint)idx ); }          T& operator[]( int idx ) { return *_getPtr( (uint)idx ); }
121          const T& operator[]( int idx ) const { return *_getPtr( (uint)idx ); }          const T& operator[]( int idx ) const { return *_getPtr( (uint)idx ); }
122    
123          virtual SafeArray<T>* Clone() const          virtual SafeArray<T>* Clone() const;
         {  
                 SafeArray<T>* retval = new SafeArray<T>( m_size );  
                 memcpy_fast( retval->GetPtr(), m_ptr, sizeof(T) * m_size );  
                 return retval;  
         }  
   
 protected:  
         // A safe array index fetcher.  Throws an exception if the array index  
         // is outside the bounds of the array.  
         // Performance Considerations: This function adds quite a bit of overhead  
         // to array indexing and thus should be done infrequently if used in  
         // time-critical situations.  Instead of using it from inside loops, cache  
         // the pointer into a local variable and use std (unsafe) C indexes.  
         T* _getPtr( uint i ) const  
         {  
                 IndexBoundsCheckDev( Name.c_str(), i, m_size );  
                 return &m_ptr[i];  
         }  
124  };  };
125    
126  //////////////////////////////////////////////////////////////////////////////////////////  //////////////////////////////////////////////////////////////////////////////////////////
# Line 239  protected: Line 151  protected:
151          uint    m_length;                       // length of the array (active items, not buffer allocation)          uint    m_length;                       // length of the array (active items, not buffer allocation)
152    
153  protected:  protected:
154          virtual T* _virtual_realloc( int newsize )          virtual T* _virtual_realloc( int newsize );
155          {          void _MakeRoomFor_threshold( int newsize );
                 return (T*)realloc( m_ptr, newsize * sizeof(T) );  
         }  
   
 public:  
         virtual ~SafeList() throw()  
         {  
                 safe_free( m_ptr );  
         }  
156    
157          explicit SafeList( const wxChar* name=L"Unnamed" ) :          T* _getPtr( uint i ) const
                 Name( name )  
         ,       ChunkSize( DefaultChunkSize )  
         ,       m_ptr( NULL )  
         ,       m_allocsize( 0 )  
         ,       m_length( 0 )  
158          {          {
159                    IndexBoundsAssumeDev( Name.c_str(), i, m_length );
160                    return &m_ptr[i];
161          }          }
162    
163          explicit SafeList( int initialSize, const wxChar* name=L"Unnamed" ) :  public:
164                  Name( name )          virtual ~SafeList() throw();
165          ,       ChunkSize( DefaultChunkSize )          explicit SafeList( const wxChar* name=L"Unnamed" );
166          ,       m_ptr( (T*)malloc( initialSize * sizeof(T) ) )          explicit SafeList( int initialSize, const wxChar* name=L"Unnamed" );
167          ,       m_allocsize( initialSize )          virtual SafeList<T>* Clone() const;
168          ,       m_length( 0 )  
169          {          void Remove( int index );
170                  if( m_ptr == NULL )          void MakeRoomFor( int blockSize );
171                          throw Exception::OutOfMemory();  
172            T& New();
173                  for( int i=0; i<m_allocsize; ++i )          int Add( const T& src );
174                  {          T& AddNew( const T& src );
                         new (&m_ptr[i]) T();  
                 }  
   
         }  
175    
176          // Returns the size of the list, as according to the array type.  This includes          // Returns the size of the list, as according to the array type.  This includes
177          // mapped items only.  The actual size of the allocation may differ.          // mapped items only.  The actual size of the allocation may differ.
# Line 289  public: Line 186  public:
186                  m_length = m_allocsize;                  m_length = m_allocsize;
187          }          }
188    
         // Ensures that the allocation is large enough to fit data of the  
         // amount requested.  The memory allocation is not resized smaller.  
         void MakeRoomFor( int blockSize )  
         {  
                 if( blockSize > m_allocsize )  
                 {  
                         const int newalloc = blockSize + ChunkSize;  
                         m_ptr = _virtual_realloc( newalloc );  
                         if( m_ptr == NULL )  
                         {  
                                 throw Exception::OutOfMemory(  
                                         // English Diagnostic message:  
                                         wxsFormat(  
                                                 L"Out-of-memory on SafeList block re-allocation.\n"  
                                                 L"Name: %s, Old size: %d bytes, New size: %d bytes",  
                                                 Name.c_str(), m_allocsize, newalloc  
                                         ),  
   
                                         wxsFormat( _("Out of memory, trying to allocate %d bytes."), newalloc )  
                                 );  
                         }  
   
                         for( ; m_allocsize<newalloc; ++m_allocsize )  
                         {  
                                 new (&m_ptr[m_allocsize]) T();  
                         }  
                 }  
         }  
   
189          void GrowBy( int items )          void GrowBy( int items )
190          {          {
191                  MakeRoomFor( m_length + ChunkSize + items + 1 );                  MakeRoomFor( m_length + ChunkSize + items + 1 );
# Line 329  public: Line 197  public:
197                  m_length = 0;                  m_length = 0;
198          }          }
199    
         // Appends an item to the end of the list and returns a handle to it.  
         T& New()  
         {  
                 _MakeRoomFor_threshold( m_length + 1 );  
                 return m_ptr[m_length++];  
         }  
   
200          // Gets an element of this memory allocation much as if it were an array.          // Gets an element of this memory allocation much as if it were an array.
201          // DevBuilds : Generates assertion if the index is invalid.          // DevBuilds : Generates assertion if the index is invalid.
202          T& operator[]( int idx )                                { return *_getPtr( (uint)idx ); }          T& operator[]( int idx )                                { return *_getPtr( (uint)idx ); }
# Line 346  public: Line 207  public:
207    
208          T& GetLast()                    { return m_ptr[m_length-1]; }          T& GetLast()                    { return m_ptr[m_length-1]; }
209          const T& GetLast() const{ return m_ptr[m_length-1]; }          const T& GetLast() const{ return m_ptr[m_length-1]; }
   
         int Add( const T& src )  
         {  
                 _MakeRoomFor_threshold( m_length + 1 );  
                 m_ptr[m_length] = src;  
                 return m_length++;  
         }  
   
         // Same as Add, but returns the handle of the new object instead of it's array index.  
         T& AddNew( const T& src )  
         {  
                 _MakeRoomFor_threshold( m_length + 1 );  
                 m_ptr[m_length] = src;  
                 return m_ptr[m_length];  
         }  
   
         // Performs a standard array-copy removal of the given item.  All items past the  
         // given item are copied over.  
         // DevBuilds : Generates assertion if the index is invalid.  
         void Remove( int index )  
         {  
                 IndexBoundsCheckDev( Name.c_str(), index, m_length );  
   
                 int copylen = m_length - index;  
                 if( copylen > 0 )  
                         memcpy_fast( &m_ptr[index], &m_ptr[index+1], copylen );  
         }  
   
         virtual SafeList<T>* Clone() const  
         {  
                 SafeList<T>* retval = new SafeList<T>( m_length );  
                 memcpy_fast( retval->m_ptr, m_ptr, sizeof(T) * m_length );  
                 return retval;  
         }  
   
 protected:  
   
         void _MakeRoomFor_threshold( int newsize )  
         {  
                 MakeRoomFor( newsize + ChunkSize );  
         }  
   
         // A safe array index fetcher.  Throws an exception if the array index  
         // is outside the bounds of the array.  
         // Performance Considerations: This function adds quite a bit of overhead  
         // to array indexing and thus should be done infrequently if used in  
         // time-critical situations.  Instead of using it from inside loops, cache  
         // the pointer into a local variable and use std (unsafe) C indexes.  
         T* _getPtr( uint i ) const  
         {  
                 IndexBoundsCheckDev( Name.c_str(), i, m_length );  
                 return &m_ptr[i];  
         }  
210  };  };
211    
212  // --------------------------------------------------------------------------------------  // --------------------------------------------------------------------------------------
213  //  SafeAlignedArray class  //  SafeAlignedArray<T>
214  // --------------------------------------------------------------------------------------  // --------------------------------------------------------------------------------------
215  // Handy little class for allocating a resizable memory block, complete with  // Handy little class for allocating a resizable memory block, complete with
216  // exception-based error handling and automatic cleanup.  // exception-based error handling and automatic cleanup.
# Line 411  protected: Line 219  protected:
219  template< typename T, uint Alignment >  template< typename T, uint Alignment >
220  class SafeAlignedArray : public SafeArray<T>  class SafeAlignedArray : public SafeArray<T>
221  {  {
222  protected:          typedef SafeArray<T> _parent;
         T* _virtual_realloc( int newsize )  
         {  
                 return (T*)( ( this->m_ptr == NULL ) ?  
                         _aligned_malloc( newsize * sizeof(T), Alignment ) :  
                         _aligned_realloc( this->m_ptr, newsize * sizeof(T), Alignment )  
                 );  
         }  
223    
224          // Appends "(align: xx)" to the name of the allocation in devel builds.  protected:
225          // Maybe useful,maybe not... no harm in attaching it. :D          T* _virtual_realloc( int newsize );
226    
227  public:  public:
228          virtual ~SafeAlignedArray()          using _parent::operator[];
229          {  
230                  safe_aligned_free( this->m_ptr );          virtual ~SafeAlignedArray() throw();
                 // mptr is set to null, so the parent class's destructor won't re-free it.  
         }  
231    
232          explicit SafeAlignedArray( const wxChar* name=L"Unnamed" ) :          explicit SafeAlignedArray( const wxChar* name=L"Unnamed" ) :
233                  SafeArray<T>::SafeArray( name )                  SafeArray<T>::SafeArray( name )
234          {          {
235          }          }
236    
237          explicit SafeAlignedArray( int initialSize, const wxChar* name=L"Unnamed" ) :          explicit SafeAlignedArray( int initialSize, const wxChar* name=L"Unnamed" );
238                  SafeArray<T>::SafeArray(          virtual SafeAlignedArray<T,Alignment>* Clone() const;
                         name,  
                         (T*)_aligned_malloc( initialSize * sizeof(T), Alignment ),  
                         initialSize  
                 )  
         {  
         }  
   
         virtual SafeAlignedArray<T,Alignment>* Clone() const  
         {  
                 SafeAlignedArray<T,Alignment>* retval = new SafeAlignedArray<T,Alignment>( this->m_size );  
                 memcpy_fast( retval->GetPtr(), this->m_ptr, sizeof(T) * this->m_size );  
                 return retval;  
         }  
239  };  };
240    
   
 // For lack of a better place for now (they depend on SafeList so they can't go in StringUtil)  
 extern void SplitString( SafeList<wxString>& dest, const wxString& src, const wxString& delims );  
 extern void JoinString( wxString& dest, const SafeList<wxString>& src, const wxString& separator );  

Legend:
Removed from v.31  
changed lines
  Added in v.62

  ViewVC Help
Powered by ViewVC 1.1.22