// NeL - MMORPG Framework // Copyright (C) 2010 Winch Gate Property Limited // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as // published by the Free Software Foundation, either version 3 of the // License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Affero General Public License for more details. // // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . #ifndef NL_PS_ALLOCATOR_H #define NL_PS_ALLOCATOR_H #include "nel/misc/time_nl.h" #include "nel/misc/contiguous_block_allocator.h" // #include namespace NL3D { #ifdef NL_OS_WINDOWS # if (__SGI_STL_PORT > 0x449) && (__SGI_STL_PORT < 0x460) || !defined(NL_DONT_USE_EXTERNAL_CODE) // fast mem alloc of particle systems only on windows for now // // PS_FAST_ALLOC // for fast alloc //# define PS_FAST_ALLOC # endif #endif // NL_OS_WINDOWS #ifndef PS_FAST_ALLOC // the following macros, that redefines new & delete for classes of ps, is now empty // NB : When using NL_MEMORY, we solve the redefinition of new errors as follow : // // PS_FAST_OBJ_ALLOC # define PS_FAST_OBJ_ALLOC // Partial specialization tips for vectors. For non-windows version it just fallback on the default allocator // To define a vector of type T, one must do : CPSVector::V MyVector; template struct CPSVector { typedef std::vector > V; }; // partial specialisation tips for multimap template > struct CPSMultiMap { #ifdef NL_OS_MAC typedef std::multimap M; #else typedef std::multimap > M; #endif }; #else // current contiguous block allocator to be used by the particle system allocator. std::allocator is used if no such allocator is provided extern NLMISC::CContiguousBlockAllocator *PSBlockAllocator; // an stl allocator for objects used in particle systems (vectors ..) // STLPort 4.5.x version of allocator : written by Nevrax #if(__SGI_STL_PORT > 0x449) && (__SGI_STL_PORT < 0x460) template class CPSAllocator { public: typedef size_t size_type; typedef ptrdiff_t difference_type; typedef T *pointer; typedef const T *const_pointer; typedef T& reference; typedef const T& const_reference; typedef T value_type; pointer address(reference x) const { return &x; } const_pointer address(const_reference x) const { return &x; } CPSAllocator() {} CPSAllocator& operator=(const CPSAllocator &other) { return *this; } private: typedef NLMISC::CContiguousBlockAllocator *TBlocAllocPtr; public: pointer allocate(size_type n, const void *hint) { ++NumPSAlloc; TBlocAllocPtr *result; // prefix the block to say it comes from a contiguous block allocator or not if (PSBlockAllocator) { result = (TBlocAllocPtr *) PSBlockAllocator->alloc(n * sizeof(T) + sizeof(TBlocAllocPtr *)); *result = PSBlockAllocator; // mark as a block from block allocator } else { result = (TBlocAllocPtr *) _Alloc.allocate(n * sizeof(T) + sizeof(TBlocAllocPtr *)); *result = NULL; // mark as a stl block } return (pointer) (result + 1); // usable space starts after header } void deallocate(pointer p, size_type n) { ++NumDealloc; --NumPSAlloc; if (!p) return; pointer realAddress = (pointer) ((uint8 *) p - sizeof(TBlocAllocPtr *)); if (* (TBlocAllocPtr *) realAddress) { // block comes from a block allocator (*(TBlocAllocPtr *) realAddress)->free((void *) realAddress, n * sizeof(T) + sizeof(TBlocAllocPtr *)); } else { // block comes from the stl allocator _Alloc.deallocate((uint8 *) realAddress, n * sizeof(T) + sizeof(TBlocAllocPtr *)); } } void construct(pointer p, const T& val) { new (p) T(val); } void destroy(pointer p) { p->~T(); } // stl rebind template CPSAllocator& __stl_alloc_rebind(CPSAllocator<_Tp>& __a, const U*) { return (CPSAllocator&)(__a); } template CPSAllocator __stl_alloc_create(const CPSAllocator<_Tp>&, const U*) { return CPSAllocator(); } private: std::allocator _Alloc; }; // STLPort 4.6.x and 5.0.x version of allocator : written by Neverborn Entertainment #elif(__SGI_STL_PORT > 0x459) template class CPSAllocator { public: typedef T value_type; typedef value_type *pointer; typedef const T *const_pointer; typedef T& reference; typedef const T& const_reference; typedef size_t size_type; typedef ptrdiff_t difference_type; #ifdef _STLP_MEMBER_TEMPLATE_CLASSES template struct rebind { typedef CPSAllocator other; }; #endif CPSAllocator() _STLP_NOTHROW {} #ifdef _STLP_MEMBER_TEMPLATES template CPSAllocator(const CPSAllocator&) _STLP_NOTHROW {} #endif CPSAllocator(const CPSAllocator&) _STLP_NOTHROW {} CPSAllocator& operator=(const CPSAllocator &other) { return *this; } ~CPSAllocator() _STLP_NOTHROW {} pointer address(reference x) const { return &x; } const_pointer address(const_reference x) const { return &x; } private: typedef NLMISC::CContiguousBlockAllocator *TBlocAllocPtr; public: pointer allocate(size_type n, const void* = 0) { ++NumPSAlloc; TBlocAllocPtr *result; // prefix the block to say it comes from a contiguous block allocator or not if (PSBlockAllocator) { result = (TBlocAllocPtr *) PSBlockAllocator->alloc(n * sizeof(T) + sizeof(TBlocAllocPtr *)); *result = PSBlockAllocator; // mark as a block from block allocator } else { result = (TBlocAllocPtr *) _Alloc.allocate(n * sizeof(T) + sizeof(TBlocAllocPtr *)); *result = NULL; // mark as a stl block } return (pointer) (result + 1); // usable space starts after header } void deallocate(pointer p, size_type n) { ++NumDealloc; --NumPSAlloc; if (!p) return; pointer realAddress = (pointer) ((uint8 *) p - sizeof(TBlocAllocPtr *)); if (* (TBlocAllocPtr *) realAddress) { // block comes from a block allocator (*(TBlocAllocPtr *) realAddress)->free((void *) realAddress, n * sizeof(T) + sizeof(TBlocAllocPtr *)); } else { // block comes from the stl allocator _Alloc.deallocate((uint8 *) realAddress, n * sizeof(T) + sizeof(TBlocAllocPtr *)); } } void construct(pointer p, const T& val) { new (p) T(val); } void destroy(pointer p) { p->~T(); } size_type max_size() const _STLP_NOTHROW { return size_t(-1) / sizeof(value_type); } // stl rebind template CPSAllocator& __stl_alloc_rebind(CPSAllocator<_Tp>& __a, const U*) { return (CPSAllocator&)(__a); } // stl create template CPSAllocator __stl_alloc_create(const CPSAllocator<_Tp>&, const U*) { return CPSAllocator(); } private: std::allocator _Alloc; }; #endif // allocation of objects of ps (to be used inside base class declaration, replaces operator new & delete) # define PS_FAST_OBJ_ALLOC \ void *operator new(size_t size) { return PSFastMemAlloc((uint) size); }\ void operator delete(void *block) { PSFastMemFree(block); } // Partial specialization tips for vectors // To define a vector of type T, one must do : CPSVector::V MyVector; template struct CPSVector { typedef std::vector > V; }; // partial specialisation tips for multimap template > struct CPSMultiMap { typedef std::multimap > M; }; extern uint NumPSAlloc; extern uint NumDealloc; // allocation of memory block for objects of a particle system void *PSFastMemAlloc(uint numBytes); void PSFastMemFree(void *block); #endif // PS_FAST_ALLOC } // NL3D #endif // NL_PS_ALLOCATOR_H