src/tools/tDecorator.h

Go to the documentation of this file.
00001 /*
00002 
00003 *************************************************************************
00004 
00005 ArmageTron -- Just another Tron Lightcycle Game in 3D.
00006 Copyright (C) 2005  by Manuel Moos
00007 and the AA DevTeam (see the file AUTHORS(.txt) in the main source directory)
00008 
00009 **************************************************************************
00010 
00011 This program is free software; you can redistribute it and/or
00012 modify it under the terms of the GNU General Public License
00013 as published by the Free Software Foundation; either version 2
00014 of the License, or (at your option) any later version.
00015 
00016 This program is distributed in the hope that it will be useful,
00017 but WITHOUT ANY WARRANTY; without even the implied warranty of
00018 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00019 GNU General Public License for more details.
00020 
00021 You should have received a copy of the GNU General Public License
00022 along with this program; if not, write to the Free Software
00023 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
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     // only public to shut up compiler warnings
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         // add decorator to list and request
00110         decorator.Insert( decorators_ );
00111         updateRequired_ = true;
00112     }
00113 
00114     void CalculateOffsets()
00115     {
00116         // early exit if there is nothing to od
00117         if ( !updateRequired_ )
00118             return;
00119 
00120         // get start offset from base class
00121         offset_ = 0;
00122         if ( base_ )
00123         {
00124             base_->CalculateOffsets();
00125             offset_ = base_->offset_;
00126         }
00127 
00128         // iterate over listed decorators
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         // iterate over listed decorators
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         // iterate over listed decorators
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         // check whether the beginnings of this and the base class are the same; the
00221         // offset calculation relies on that.
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         // insert into management list
00256         manager.AddDecorator( *this );
00257     }
00258 
00260     Decoration & Get( Decorated & object )
00261     {
00262         // pointer magic to get to the place of the decoration in decorator spacew
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 // *    Allocate
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     // delegate to manager
00355     tDecoratableManagerBase & manager = GetManager();
00356     return manager.Allocate( size, classn, file, line );
00357 }
00358 
00359 // *******************************************************************************
00360 // *
00361 // *    Allocate
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 // *    Free
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     // deregister with manager
00393     tDecoratableManagerBase & manager = GetManager();
00394     manager.Free( ptr, classn, file, line );
00395 }
00396 
00397 // *******************************************************************************
00398 // *
00399 // *    Free
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

Generated on Sat Mar 15 22:55:59 2008 for Armagetron Advanced by  doxygen 1.5.4