Torque3D Documentation / _generateds / frameAllocator.h

frameAllocator.h

Engine/source/core/frameAllocator.h

More...

Classes:

class

Temporary memory pool for per-frame allocations.

class

Helper class to deal with FrameAllocator usage.

class

Class for temporary variables that you want to allocate easily using the FrameAllocator.

Public Defines

define
FRAME_TEMP_NC_SPEC(type)    template<> \
   inline <type>::(    ) \
   { \
      (  > 0, "Allocating   with less than one instance" ); \
      mWaterMark = (); \
      mMemory = reinterpret_cast<type *>( ( sizeof( type ) *  ) ); \
      mNumObjectsInMemory = 0; \
   } \
   template<>\
   inline <type>::~() \
   { \
      ( mWaterMark ); \
   } \
define

This #define is used by the FrameAllocator to align starting addresses to be byte aligned to this value.

Public Functions

Detailed Description

Public Defines

FRAME_TEMP_NC_SPEC(type)    template<> \
   inline <type>::(    ) \
   { \
      (  > 0, "Allocating   with less than one instance" ); \
      mWaterMark = (); \
      mMemory = reinterpret_cast<type *>( ( sizeof( type ) *  ) ); \
      mNumObjectsInMemory = 0; \
   } \
   template<>\
   inline <type>::~() \
   { \
      ( mWaterMark ); \
   } \
FRAMEALLOCATOR_BYTE_ALIGNMENT() 4

This #define is used by the FrameAllocator to align starting addresses to be byte aligned to this value.

This is important on the 360 and possibly on other platforms as well. Use this #define anywhere alignment is needed.

NOTE: Do not change this value per-platform unless you have a very good reason for doing so. It has the potential to cause inconsistencies in memory which is allocated and expected to be contiguous.

Public Functions

FRAME_TEMP_NC_SPEC(bool )

FRAME_TEMP_NC_SPEC(char )

FRAME_TEMP_NC_SPEC(double )

FRAME_TEMP_NC_SPEC(float )

FRAME_TEMP_NC_SPEC(int )

FRAME_TEMP_NC_SPEC(short )

FRAME_TEMP_NC_SPEC(unsigned char )

FRAME_TEMP_NC_SPEC(unsigned int )

FRAME_TEMP_NC_SPEC(unsigned short )

  1
  2//-----------------------------------------------------------------------------
  3// Copyright (c) 2012 GarageGames, LLC
  4//
  5// Permission is hereby granted, free of charge, to any person obtaining a copy
  6// of this software and associated documentation files (the "Software"), to
  7// deal in the Software without restriction, including without limitation the
  8// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  9// sell copies of the Software, and to permit persons to whom the Software is
 10// furnished to do so, subject to the following conditions:
 11//
 12// The above copyright notice and this permission notice shall be included in
 13// all copies or substantial portions of the Software.
 14//
 15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 18// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 20// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 21// IN THE SOFTWARE.
 22//-----------------------------------------------------------------------------
 23
 24#ifndef _FRAMEALLOCATOR_H_
 25#define _FRAMEALLOCATOR_H_
 26
 27#ifndef _PLATFORM_H_
 28#include "platform/platform.h"
 29#endif
 30
 31/// This #define is used by the FrameAllocator to align starting addresses to
 32/// be byte aligned to this value. This is important on the 360 and possibly
 33/// on other platforms as well. Use this #define anywhere alignment is needed.
 34///
 35/// NOTE: Do not change this value per-platform unless you have a very good
 36/// reason for doing so. It has the potential to cause inconsistencies in 
 37/// memory which is allocated and expected to be contiguous.
 38#define FRAMEALLOCATOR_BYTE_ALIGNMENT 4
 39
 40/// Temporary memory pool for per-frame allocations.
 41///
 42/// In the course of rendering a frame, it is often necessary to allocate
 43/// many small chunks of memory, then free them all in a batch. For instance,
 44/// say we're allocating storage for some vertex calculations:
 45///
 46/// @code
 47///   // Get FrameAllocator memory...
 48///   U32 waterMark = FrameAllocator::getWaterMark();
 49///   F32 * ptr = (F32*)FrameAllocator::alloc(sizeof(F32)*2*targetMesh->vertsPerFrame);
 50///
 51///   ... calculations ...
 52///
 53///   // Free frameAllocator memory
 54///   FrameAllocator::setWaterMark(waterMark);
 55/// @endcode
 56class FrameAllocator
 57{
 58   static U8*   smBuffer;
 59   static U32   smHighWaterMark;
 60   static U32   smWaterMark;
 61
 62#ifdef TORQUE_DEBUG
 63   static U32 smMaxFrameAllocation;
 64#endif
 65
 66  public:
 67   inline static void init(const U32 frameSize);
 68   inline static void destroy();
 69
 70   inline static void* alloc(const U32 allocSize);
 71
 72   inline static void setWaterMark(const U32);
 73   inline static U32  getWaterMark();
 74   inline static U32  getHighWaterMark();
 75
 76#ifdef TORQUE_DEBUG
 77   static U32 getMaxFrameAllocation() { return smMaxFrameAllocation; }
 78#endif
 79};
 80
 81void FrameAllocator::init(const U32 frameSize)
 82{
 83#ifdef FRAMEALLOCATOR_DEBUG_GUARD
 84   AssertISV( false, "FRAMEALLOCATOR_DEBUG_GUARD has been removed because it allows non-contiguous memory allocation by the FrameAllocator, and this is *not* ok." );
 85#endif
 86
 87   AssertFatal(smBuffer == NULL, "Error, already initialized");
 88   smBuffer = new U8[frameSize];
 89   smWaterMark = 0;
 90   smHighWaterMark = frameSize;
 91}
 92
 93void FrameAllocator::destroy()
 94{
 95   AssertFatal(smBuffer != NULL, "Error, not initialized");
 96
 97   delete [] smBuffer;
 98   smBuffer = NULL;
 99   smWaterMark = 0;
100   smHighWaterMark = 0;
101}
102
103
104void* FrameAllocator::alloc(const U32 allocSize)
105{
106   U32 _allocSize = allocSize;
107
108   AssertFatal(smBuffer != NULL, "Error, no buffer!");
109   AssertFatal(smWaterMark + _allocSize <= smHighWaterMark, "Error alloc too large, increase frame size!");
110   smWaterMark = ( smWaterMark + ( FRAMEALLOCATOR_BYTE_ALIGNMENT - 1 ) ) & (~( FRAMEALLOCATOR_BYTE_ALIGNMENT - 1 ));
111
112   // Sanity check.
113   AssertFatal( !( smWaterMark & ( FRAMEALLOCATOR_BYTE_ALIGNMENT - 1 ) ), "Frame allocation is not on a specified byte boundry." );
114
115   U8* p = &smBuffer[smWaterMark];
116   smWaterMark += _allocSize;
117
118#ifdef TORQUE_DEBUG
119   if (smWaterMark > smMaxFrameAllocation)
120      smMaxFrameAllocation = smWaterMark;
121#endif
122
123   return p;
124}
125
126
127void FrameAllocator::setWaterMark(const U32 waterMark)
128{
129   AssertFatal(waterMark < smHighWaterMark, "Error, invalid waterMark");
130   smWaterMark = waterMark;
131}
132
133U32 FrameAllocator::getWaterMark()
134{
135   return smWaterMark;
136}
137
138U32 FrameAllocator::getHighWaterMark()
139{
140   return smHighWaterMark;
141}
142
143/// Helper class to deal with FrameAllocator usage.
144///
145/// The purpose of this class is to make it simpler and more reliable to use the
146/// FrameAllocator. Simply use it like this:
147///
148/// @code
149/// FrameAllocatorMarker mem;
150///
151/// char *buff = (char*)mem.alloc(100);
152/// @endcode
153///
154/// When you leave the scope you defined the FrameAllocatorMarker in, it will
155/// automatically restore the watermark on the FrameAllocator. In situations
156/// with complex branches, this can be a significant headache remover, as you
157/// don't have to remember to reset the FrameAllocator on every posssible branch.
158class FrameAllocatorMarker
159{
160   U32 mMarker;
161
162public:
163   FrameAllocatorMarker()
164   {
165      mMarker = FrameAllocator::getWaterMark();
166   }
167
168   ~FrameAllocatorMarker()
169   {
170      FrameAllocator::setWaterMark(mMarker);
171   }
172
173   void* alloc(const U32 allocSize) const
174   {
175      return FrameAllocator::alloc(allocSize);
176   }
177
178   template<typename T>
179   T* alloc(const U32 numElements) const
180   {
181      return reinterpret_cast<T *>(FrameAllocator::alloc(numElements * sizeof(T)));
182   }
183};
184
185/// Class for temporary variables that you want to allocate easily using
186/// the FrameAllocator. For example:
187/// @code
188/// FrameTemp<char> tempStr(32); // NOTE! This parameter is NOT THE SIZE IN BYTES. See constructor docs.
189/// dStrcat( tempStr, SomeOtherString, 32 * sizeof(char) );
190/// tempStr[2] = 'l';
191/// Con::printf( tempStr );
192/// Con::printf( "Foo: %s", ~tempStr );
193/// @endcode
194///
195/// This will automatically handle getting and restoring the watermark of the
196/// FrameAllocator when it goes out of scope. You should notice the strange
197/// operator in front of tempStr on the printf call. This is normally a unary
198/// operator for ones-complement, but in this class it will simply return the
199/// memory of the allocation. It's the same as doing (const char *)tempStr
200/// in the above case. The reason why it is necessary for the second printf
201/// and not the first is because the second one is taking a variable arg
202/// list and so it isn't getting the cast so that it's cast operator can
203/// properly return the memory instead of the FrameTemp object itself.
204///
205/// @note It is important to note that this object is designed to just be a
206/// temporary array of a dynamic size. Some wierdness may occur if you try
207/// to perform crazy pointer stuff with it using regular operators on it.
208template<class T>
209class FrameTemp
210{
211protected:
212   U32 mWaterMark;
213   T *mMemory;
214   U32 mNumObjectsInMemory;
215
216public:
217   /// Constructor will store the FrameAllocator watermark and allocate the memory off
218   /// of the FrameAllocator.
219   ///
220   /// @note It is important to note that, unlike the FrameAllocatorMarker and the
221   /// FrameAllocator itself, the argument to allocate is NOT the size in bytes,
222   /// doing:
223   /// @code
224   /// FrameTemp<F64> f64s(5);
225   /// @endcode
226   /// Is the same as
227   /// @code
228   /// F64 *f64s = new F64[5];
229   /// @endcode
230   ///
231   /// @param   count   The number of objects to allocate
232   FrameTemp( const U32 count = 1 ) : mNumObjectsInMemory( count )
233   {
234      AssertFatal( count > 0, "Allocating a FrameTemp with less than one instance" );
235      mWaterMark = FrameAllocator::getWaterMark();
236      mMemory = reinterpret_cast<T *>( FrameAllocator::alloc( sizeof( T ) * count ) );
237
238      for( S32 i = 0; i < mNumObjectsInMemory; i++ )
239         constructInPlace<T>( &mMemory[i] );
240   }
241
242   /// Destructor restores the watermark
243   ~FrameTemp()
244   {
245      // Call destructor
246      for( S32 i = 0; i < mNumObjectsInMemory; i++ )
247         destructInPlace<T>( &mMemory[i] );
248
249      FrameAllocator::setWaterMark( mWaterMark );
250   }
251
252   /// NOTE: This will return the memory, NOT perform a ones-complement
253   T* operator~() { return mMemory; };
254   /// NOTE: This will return the memory, NOT perform a ones-complement
255   const T* operator~() const { return mMemory; };
256
257   /// NOTE: This will dereference the memory, NOT do standard unary plus behavior
258   T& operator+() { return *mMemory; };
259   /// NOTE: This will dereference the memory, NOT do standard unary plus behavior
260   const T& operator+() const { return *mMemory; };
261
262   T& operator*() { return *mMemory; };
263   const T& operator*() const { return *mMemory; };
264
265   T** operator&() { return &mMemory; };
266   const T** operator&() const { return &mMemory; };
267
268   operator T*() { return mMemory; }
269   operator const T*() const { return mMemory; }
270
271   operator T&() { return *mMemory; }
272   operator const T&() const { return *mMemory; }
273
274   operator T() { return *mMemory; }
275   operator const T() const { return *mMemory; }
276   
277   T& operator []( U32 i ) { return mMemory[ i ]; }
278   const T& operator []( U32 i ) const { return mMemory[ i ]; }
279
280   T& operator []( S32 i ) { return mMemory[ i ]; }
281   const T& operator []( S32 i ) const { return mMemory[ i ]; }
282
283   /// @name Vector-like Interface
284   /// @{
285   T *address() const { return mMemory; }
286   dsize_t size() const { return mNumObjectsInMemory; }
287   /// @}
288};
289
290//-----------------------------------------------------------------------------
291// FrameTemp specializations for types with no constructor/destructor
292#define FRAME_TEMP_NC_SPEC(type) \
293   template<> \
294   inline FrameTemp<type>::FrameTemp( const U32 count ) \
295   { \
296      AssertFatal( count > 0, "Allocating a FrameTemp with less than one instance" ); \
297      mWaterMark = FrameAllocator::getWaterMark(); \
298      mMemory = reinterpret_cast<type *>( FrameAllocator::alloc( sizeof( type ) * count ) ); \
299      mNumObjectsInMemory = 0; \
300   } \
301   template<>\
302   inline FrameTemp<type>::~FrameTemp() \
303   { \
304      FrameAllocator::setWaterMark( mWaterMark ); \
305   } \
306
307FRAME_TEMP_NC_SPEC(char);
308FRAME_TEMP_NC_SPEC(float);
309FRAME_TEMP_NC_SPEC(double);
310FRAME_TEMP_NC_SPEC(bool);
311FRAME_TEMP_NC_SPEC(int);
312FRAME_TEMP_NC_SPEC(short);
313
314FRAME_TEMP_NC_SPEC(unsigned char);
315FRAME_TEMP_NC_SPEC(unsigned int);
316FRAME_TEMP_NC_SPEC(unsigned short);
317
318#undef FRAME_TEMP_NC_SPEC
319
320//-----------------------------------------------------------------------------
321
322#endif  // _H_FRAMEALLOCATOR_
323