00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 #ifndef ArmageTron_DECORATOR_H
00030 #define ArmageTron_DECORATOR_H
00031
00032 #include "tMemManager.h"
00033 #include "tLinkedList.h"
00034 #include "tError.h"
00035
00037 class tDecoratableIndicator{};
00038
00040 template <class Decorated> class tIsDecoratable
00041 {
00042 private:
00043 struct Ret{ char a; char b; };
00044 static char TestDecoratable(tDecoratableIndicator const &);
00045 static Decorated & decorated_;
00046
00047 public:
00048
00049 static Ret TestDecoratable(...);
00050
00053 enum { DECORATABLE=(sizeof(TestDecoratable( decorated_ ) ) <= sizeof( char) ) };
00054 };
00055
00056
00057
00058 class tDecoratableManagerBase;
00059
00061 class tDecoratorBase: public tListItem< tDecoratorBase >
00062 {
00063 friend class tDecoratableManagerBase;
00064 protected:
00065 size_t offset_;
00066 tDecoratorBase():offset_(0xbaad){};
00067 private:
00068 virtual size_t GetSize() const = 0;
00069 virtual void Construct( void * decoration ) const = 0;
00070 virtual void Destruct( void * decoration ) const = 0;
00071
00072 tDecoratorBase( tDecoratorBase const & );
00073 tDecoratorBase & operator =( tDecoratorBase const & );
00074 };
00075
00076
00077
00078
00080 class tDecoratableManagerBase
00081 {
00082 public:
00083 tDecoratableManagerBase()
00084 : base_( 0 ), refCount_( 0 ), decorators_( 0 )
00085 , updateRequired_( true ), offset_( 0 )
00086 {
00087 }
00088
00090 size_t GetSize() const
00091 {
00092 tASSERT( !updateRequired_ );
00093
00094 return offset_;
00095 }
00096
00098 size_t Reserve( size_t allocate, size_t alignment = 4 )
00099 {
00100 offset_ += allocate;
00101 offset_ = (( offset_ + alignment - 1 ) / alignment ) * alignment;
00102 return offset_;
00103 }
00104
00105 void AddDecorator( tDecoratorBase & decorator )
00106 {
00107 tASSERT( refCount_ == 0 );
00108
00109
00110 decorator.Insert( decorators_ );
00111 updateRequired_ = true;
00112 }
00113
00114 void CalculateOffsets()
00115 {
00116
00117 if ( !updateRequired_ )
00118 return;
00119
00120
00121 offset_ = 0;
00122 if ( base_ )
00123 {
00124 base_->CalculateOffsets();
00125 offset_ = base_->offset_;
00126 }
00127
00128
00129 tDecoratorBase * run = decorators_;
00130 while ( run )
00131 {
00132 run->offset_ = Reserve( run->GetSize() );
00133 run = run->Next();
00134 }
00135
00136 updateRequired_ = false;
00137 }
00138
00139 void ConstructAll( void * decorated )
00140 {
00141 if ( base_ )
00142 {
00143 base_->ConstructAll( decorated );
00144 }
00145
00146
00147 tDecoratorBase * run = decorators_;
00148 while ( run )
00149 {
00150 void * decoration = static_cast< char * >( decorated ) - run->offset_;
00151 run->Construct( decoration );
00152 run = run->Next();
00153 }
00154 }
00155
00156 void DestructAll( void * decorated )
00157 {
00158 if ( base_ )
00159 {
00160 base_->DestructAll( decorated );
00161 }
00162
00163
00164 tDecoratorBase * run = decorators_;
00165 while ( run )
00166 {
00167 void * decoration = static_cast< char * >( decorated ) - run->offset_;
00168 run->Destruct( decoration );
00169 run = run->Next();
00170 }
00171 }
00172
00174 void * Allocate( size_t size, const char * classn, const char * file, int line );
00175
00177 void Free( void * ptr, const char * classn, const char * file, int line );
00178 protected:
00179 tDecoratableManagerBase * base_;
00180 size_t refCount_;
00181 private:
00182 tDecoratableManagerBase( tDecoratableManagerBase const & );
00183 tDecoratableManagerBase & operator =( tDecoratableManagerBase const & );
00184
00185 tDecoratorBase * decorators_;
00186
00187
00188 bool updateRequired_;
00189 size_t offset_;
00190 };
00191
00193 template<class Decorated> class tDecoratableManager: public tDecoratableManagerBase
00194 {
00195 public:
00197 static void * Allocate( size_t size, const char * classn, const char * file, int line );
00198 static void * Allocate( size_t size );
00199
00201 static void Free( void * ptr, const char * classn, const char * file, int line );
00202 static void Free( void * ptr );
00203
00205 static tDecoratableManager & GetManager()
00206 {
00207 static tDecoratableManager manager;
00208 return manager;
00209 };
00210
00211 private:
00213 typedef typename Decorated::DecoratableBase_ DecoratedBase;
00214
00215 template< bool > struct tBoolToType{};
00216
00217 tDecoratableManagerBase * GetBase( tBoolToType< true > )
00218 {
00219 #ifdef DEBUG
00220
00221
00222 Decorated * d = NULL;
00223 DecoratedBase * b = d;
00224 tASSERT( b == NULL );
00225 #endif
00226
00227 return &tDecoratableManager< DecoratedBase >::GetManager();
00228 }
00229
00230 tDecoratableManagerBase * GetBase( tBoolToType< false > )
00231 {
00232 return NULL;
00233 }
00234
00235 tDecoratableManager()
00236 {
00237 base_ = GetBase( tBoolToType< tIsDecoratable< DecoratedBase >::DECORATABLE >() );
00238 }
00239 };
00240
00241
00242
00244 template< class DecoratedDerived, class Decoration > class tDecorator: public tDecoratorBase
00245 {
00246 public:
00248 typedef typename DecoratedDerived::Decoratable_ Decorated;
00249
00251 tDecorator()
00252 {
00253 tDecoratableManager< Decorated > & manager = tDecoratableManager< Decorated >::GetManager();
00254
00255
00256 manager.AddDecorator( *this );
00257 }
00258
00260 Decoration & Get( Decorated & object )
00261 {
00262
00263 char * endOfPointerSpace = static_cast< char * >( static_cast< void * >( &object ) );
00264 char * allocatedSlot = endOfPointerSpace - offset_;
00265 Decoration * decoration = static_cast< Decoration * >( static_cast< void * >( allocatedSlot ) );
00266
00267 return * decoration;
00268 }
00269 private:
00270 virtual size_t GetSize() const { return sizeof( Decoration ); }
00271
00272 virtual void Construct( void * decoration ) const
00273 {
00274 new(decoration) Decoration;
00275 }
00276
00277 virtual void Destruct( void * decoration ) const
00278 {
00279 static_cast< Decoration * >( decoration )->~Decoration();
00280 }
00281 };
00282
00283 template< class DecoratedDerived, class Decoration > class tDecoratorPOD: public tDecorator< DecoratedDerived, Decoration >
00284 {
00285 public:
00287 tDecoratorPOD( Decoration const & value )
00288 : value_ ( value )
00289 {
00290 }
00291
00292 private:
00293 tDecoratorPOD();
00294
00295 Decoration value_;
00296
00297 virtual void Construct( void * decoration ) const
00298 {
00299 new(decoration) Decoration;
00300 *static_cast< Decoration * >( decoration ) = value_;
00301 }
00302 };
00303
00307 #define DECORATABLE(CLASS,BASE) \
00308 public: \
00309 operator tDecoratableIndicator & () const; \
00310 typedef BASE DecoratableBase_; \
00311 typedef CLASS Decoratable_; \
00312 void * operator new ( size_t size ) THROW_BADALLOC \
00313 { \
00314 return tDecoratableManager< CLASS >::Allocate( size ); \
00315 } \
00316 void operator delete ( void * ptr ) THROW_NOTHING \
00317 { \
00318 tDecoratableManager< CLASS >::Free( ptr); \
00319 } \
00320 void * operator new (size_t size,const char * classn,const char * file,int line) THROW_BADALLOC \
00321 { \
00322 return tDecoratableManager< CLASS >::Allocate( size, classn, file, line ); \
00323 } \
00324 void operator delete (void * ptr,const char * classn, const char * file,int line) THROW_NOTHING \
00325 { \
00326 tDecoratableManager< CLASS >::Free( ptr, classn, file, line); \
00327 } \
00328 private: \
00329 void * operator new[] ( size_t size ) THROW_BADALLOC; \
00330 void operator delete[]( void * old ) THROW_NOTHING; \
00331 void * operator new[] (size_t size,const char *classn,const char * file,int line ) THROW_BADALLOC; \
00332 void operator delete[](void *ptr,const char *classname,const char * file,int line ) THROW_NOTHING; \
00333 public:
00334
00335 #define DECORATABLE_BASE(CLASS) DECORATABLE(CLASS,int)
00336
00337
00338
00339
00340
00341
00349
00350
00351 template< class Decorate >
00352 void * tDecoratableManager< Decorate >::Allocate( size_t size, const char * classn, const char * file, int line )
00353 {
00354
00355 tDecoratableManagerBase & manager = GetManager();
00356 return manager.Allocate( size, classn, file, line );
00357 }
00358
00359
00360
00361
00362
00363
00368
00369
00370 template< class Decorate >
00371 void * tDecoratableManager< Decorate >::Allocate( size_t size )
00372 {
00373 return Allocate( size, "noclass", "nofile", 0 );
00374 }
00375
00376
00377
00378
00379
00380
00387
00388
00389 template< class Decorate >
00390 void tDecoratableManager< Decorate >::Free( void * ptr, const char * classn, const char * file, int line )
00391 {
00392
00393 tDecoratableManagerBase & manager = GetManager();
00394 manager.Free( ptr, classn, file, line );
00395 }
00396
00397
00398
00399
00400
00401
00405
00406
00407 template< class Decorate >
00408 void tDecoratableManager< Decorate >::Free( void * ptr )
00409 {
00410 return Free( ptr, "noclass", "nofile", 0 );
00411 }
00412
00413 #endif