ps_allocator.h

Go to the documentation of this file.
00001 
00004 /* Copyright, 2000, 2001, 2002, 2003 Nevrax Ltd.
00005  *
00006  * This file is part of NEVRAX NEL.
00007  * NEVRAX NEL is free software; you can redistribute it and/or modify
00008  * it under the terms of the GNU General Public License as published by
00009  * the Free Software Foundation; either version 2, or (at your option)
00010  * any later version.
00011 
00012  * NEVRAX NEL is distributed in the hope that it will be useful, but
00013  * WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
00015  * General Public License for more details.
00016 
00017  * You should have received a copy of the GNU General Public License
00018  * along with NEVRAX NEL; see the file COPYING. If not, write to the
00019  * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
00020  * MA 02111-1307, USA.
00021  */
00022 
00023 #ifndef NL_PS_ALLOCATOR_H
00024 #define NL_PS_ALLOCATOR_H
00025 
00026 #include "nel/misc/time_nl.h"
00027 #include "nel/misc/contiguous_block_allocator.h"
00028 //
00029 #include <map>
00030 
00031 namespace NL3D
00032 {
00033 
00034 #ifdef NL_OS_WINDOWS
00035 #   if (__SGI_STL_PORT > 0x449) && (__SGI_STL_PORT < 0x460) || !defined(NL_DONT_USE_EXTERNAL_CODE)
00036 
00037         // fast mem alloc of particle systems only on windows for now
00038         //
00039         // PS_FAST_ALLOC // for fast alloc
00040 //#     define PS_FAST_ALLOC
00041 #   endif
00042 #endif // NL_OS_WINDOWS
00043 
00044 
00045 #ifndef PS_FAST_ALLOC
00046     // the following macros, that redefines new & delete for classes of ps, is now empty
00047     // NB : When using NL_MEMORY, we solve the redefinition of new errors as follow :
00048     //
00049     // PS_FAST_OBJ_ALLOC
00050 #   define PS_FAST_OBJ_ALLOC
00051     // Partial specialization tips for vectors. For non-windows version it just fallback on the default allocator
00052     // To define a vector of type T, one must do : CPSVector<T>::V MyVector;
00053     template <class T> struct CPSVector
00054     {
00055         typedef std::vector<T, std::allocator<T> > V;
00056     };
00057     // partial specialisation tips for multimap
00058     template <class T, class U, class Pr = std::less<T> > struct CPSMultiMap
00059     {
00060 #ifdef NL_OS_MAC
00061         typedef std::multimap<T, U, Pr > M;
00062 #else
00063         typedef std::multimap<T, U, Pr, std::allocator<T> > M;
00064 #endif
00065     };
00066 
00067 #else
00068 
00069     // current contiguous block allocator to be used by the particle system allocator. std::allocator is used if no such allocator is provided
00070     extern NLMISC::CContiguousBlockAllocator *PSBlockAllocator;
00071 
00072     // an stl allocator for objects used in particle systems (vectors ..)
00073 
00074 // STLPort 4.5.x version of allocator : written by Nevrax
00075 #if(__SGI_STL_PORT > 0x449) && (__SGI_STL_PORT < 0x460)
00076     template<class T> class CPSAllocator
00077     {
00078     public:
00079         typedef size_t size_type;
00080         typedef ptrdiff_t difference_type;
00081         typedef T *pointer;
00082         typedef const T *const_pointer;
00083         typedef T& reference;
00084         typedef const T& const_reference;
00085         typedef T value_type;
00086         pointer address(reference x) const { return &x; }
00087         const_pointer address(const_reference x) const { return &x; }
00088         CPSAllocator() {}
00089         CPSAllocator<T>& operator=(const CPSAllocator<T> &other) { return *this; }
00090     private:
00091         typedef NLMISC::CContiguousBlockAllocator *TBlocAllocPtr;
00092     public:
00093         pointer allocate(size_type n, const void *hint)
00094         {
00095             ++NumPSAlloc;
00096             TBlocAllocPtr *result;
00097             // prefix the block to say it comes from a contiguous block allocator or not
00098             if (PSBlockAllocator)
00099             {
00100                 result = (TBlocAllocPtr *) PSBlockAllocator->alloc(n * sizeof(T) + sizeof(TBlocAllocPtr *));
00101                 *result = PSBlockAllocator; // mark as a block from block allocator
00102             }
00103             else
00104             {
00105                  result = (TBlocAllocPtr *) _Alloc.allocate(n * sizeof(T) + sizeof(TBlocAllocPtr *));
00106                  *result = NULL; // mark as a stl block
00107             }
00108             return (pointer) (result + 1); // usable space starts after header
00109         }
00110         void deallocate(pointer p, size_type n)
00111         {
00112             ++NumDealloc;
00113             --NumPSAlloc;
00114             if (!p) return;
00115             pointer realAddress = (pointer) ((uint8 *) p - sizeof(TBlocAllocPtr *));
00116             if (* (TBlocAllocPtr *) realAddress)
00117             {
00118                 // block comes from a block allocator
00119                 (*(TBlocAllocPtr *) realAddress)->free((void *) realAddress, n * sizeof(T) + sizeof(TBlocAllocPtr *));
00120             }
00121             else
00122             {
00123                 // block comes from the stl allocator
00124                 _Alloc.deallocate((uint8 *) realAddress, n * sizeof(T) + sizeof(TBlocAllocPtr *));
00125             }
00126         }
00127         void construct(pointer p, const T& val) { new (p) T(val); }
00128         void destroy(pointer p) { p->~T(); }
00129         // stl rebind
00130         template <class _Tp, class U>
00131             CPSAllocator<U>& __stl_alloc_rebind(CPSAllocator<_Tp>& __a, const U*)
00132         {
00133             return (CPSAllocator<U>&)(__a);
00134         }
00135 
00136         template <class _Tp, class U>
00137             CPSAllocator<U> __stl_alloc_create(const CPSAllocator<_Tp>&, const U*)
00138         {
00139             return CPSAllocator<U>();
00140         }
00141 
00142     private:
00143         std::allocator<uint8> _Alloc;
00144     };
00145 
00146 // STLPort 4.6.x and 5.0.x version of allocator : written by Neverborn Entertainment
00147 #elif(__SGI_STL_PORT > 0x459)
00148 
00149     template<class T> class CPSAllocator
00150     {
00151     public:
00152 
00153         typedef T value_type;
00154         typedef value_type *pointer;
00155         typedef const T *const_pointer;
00156         typedef T& reference;
00157         typedef const T& const_reference;
00158         typedef size_t size_type;
00159         typedef ptrdiff_t difference_type;
00160 
00161 #ifdef _STLP_MEMBER_TEMPLATE_CLASSES
00162         template <class U> struct rebind {
00163                 typedef CPSAllocator<U> other;
00164         };
00165 #endif
00166 
00167         CPSAllocator() _STLP_NOTHROW {}
00168 
00169 #ifdef _STLP_MEMBER_TEMPLATES
00170         template <class U> CPSAllocator(const CPSAllocator<U>&) _STLP_NOTHROW {}
00171 #endif
00172 
00173         CPSAllocator(const CPSAllocator<T>&) _STLP_NOTHROW {}
00174 
00175         CPSAllocator<T>& operator=(const CPSAllocator<T> &other) { return *this; }
00176         ~CPSAllocator() _STLP_NOTHROW {}
00177 
00178         pointer address(reference x) const { return &x; }
00179         const_pointer address(const_reference x) const { return &x; }
00180 
00181     private:
00182 
00183         typedef NLMISC::CContiguousBlockAllocator *TBlocAllocPtr;
00184 
00185     public:
00186 
00187         pointer allocate(size_type n, const void* = 0)
00188         {
00189             ++NumPSAlloc;
00190             TBlocAllocPtr *result;
00191             // prefix the block to say it comes from a contiguous block allocator or not
00192             if (PSBlockAllocator)
00193             {
00194                 result = (TBlocAllocPtr *) PSBlockAllocator->alloc(n * sizeof(T) + sizeof(TBlocAllocPtr *));
00195                 *result = PSBlockAllocator; // mark as a block from block allocator
00196             }
00197             else
00198             {
00199                 result = (TBlocAllocPtr *) _Alloc.allocate(n * sizeof(T) + sizeof(TBlocAllocPtr *));
00200                 *result = NULL; // mark as a stl block
00201             }
00202             return (pointer) (result + 1); // usable space starts after header
00203         }
00204 
00205         void deallocate(pointer p, size_type n)
00206         {
00207             ++NumDealloc;
00208             --NumPSAlloc;
00209             if (!p) return;
00210             pointer realAddress = (pointer) ((uint8 *) p - sizeof(TBlocAllocPtr *));
00211             if (* (TBlocAllocPtr *) realAddress)
00212             {
00213                 // block comes from a block allocator
00214                 (*(TBlocAllocPtr *) realAddress)->free((void *) realAddress, n * sizeof(T) + sizeof(TBlocAllocPtr *));
00215             }
00216             else
00217             {
00218                 // block comes from the stl allocator
00219                 _Alloc.deallocate((uint8 *) realAddress, n * sizeof(T) + sizeof(TBlocAllocPtr *));
00220             }
00221         }
00222 
00223         void construct(pointer p, const T& val) { new (p) T(val); }
00224         void destroy(pointer p) { p->~T(); }
00225 
00226         size_type max_size() const _STLP_NOTHROW  { return size_t(-1) / sizeof(value_type); }
00227 
00228         // stl rebind
00229         template <class _Tp, class U> CPSAllocator<U>& __stl_alloc_rebind(CPSAllocator<_Tp>& __a, const U*)
00230         {
00231             return (CPSAllocator<U>&)(__a);
00232         }
00233 
00234         // stl create
00235         template <class _Tp, class U> CPSAllocator<U> __stl_alloc_create(const CPSAllocator<_Tp>&, const U*)
00236         {
00237             return CPSAllocator<U>();
00238         }
00239 
00240     private:
00241         std::allocator<uint8> _Alloc;
00242     };
00243 
00244 #endif
00245 
00246     // allocation of objects of ps (to be used inside base class declaration, replaces operator new & delete)
00247 #   define PS_FAST_OBJ_ALLOC \
00248     void *operator new(size_t size) { return PSFastMemAlloc((uint) size); }\
00249     void operator delete(void *block) { PSFastMemFree(block); }
00250 
00251 
00252     // Partial specialization tips for vectors
00253     // To define a vector of type T, one must do : CPSVector<T>::V MyVector;
00254     template <class T> struct CPSVector
00255     {
00256         typedef std::vector<T, CPSAllocator<T> > V;
00257     };
00258     // partial specialisation tips for multimap
00259     template <class T, class U, class Pr = std::less<T> > struct CPSMultiMap
00260     {
00261         typedef std::multimap<T, U, Pr, CPSAllocator<T> > M;
00262     };
00263 
00264     extern uint NumPSAlloc;
00265     extern uint NumDealloc;
00266 
00267     // allocation of memory block for objects of a particle system
00268     void *PSFastMemAlloc(uint numBytes);
00269     void PSFastMemFree(void *block);
00270 
00271 #endif // PS_FAST_ALLOC
00272 
00273 } // NL3D
00274 
00275 #endif // NL_PS_ALLOCATOR_H

Generated on Thu Jan 7 08:26:19 2010 for NeL by  doxygen 1.6.1