2
0

FastAllocator.h 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735
  1. /*
  2. ** Command & Conquer Renegade(tm)
  3. ** Copyright 2025 Electronic Arts Inc.
  4. **
  5. ** This program is free software: you can redistribute it and/or modify
  6. ** it under the terms of the GNU General Public License as published by
  7. ** the Free Software Foundation, either version 3 of the License, or
  8. ** (at your option) any later version.
  9. **
  10. ** This program is distributed in the hope that it will be useful,
  11. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. ** GNU General Public License for more details.
  14. **
  15. ** You should have received a copy of the GNU General Public License
  16. ** along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. ///////////////////////////////////////////////////////////////////////////////
  19. // FastAllocator.h
  20. //
  21. // Implements simple and fast memory allocators. Includes sample code for
  22. // STL and overriding of specific or global new/delete.
  23. //
  24. // Allocators are very fast and prevent memory fragmentation. They use up
  25. // a little more space on average than generic new/malloc free/delete.
  26. //
  27. ///////////////////////////////////////////////////////////////////////////////
  28. #ifndef FASTALLOCATOR_H
  29. #define FASTALLOCATOR_H
  30. #if defined(_MSC_VER)
  31. #pragma once
  32. #endif
  33. //#define MEMORY_OVERWRITE_TEST
  34. ///////////////////////////////////////////////////////////////////////////////
  35. // Include files
  36. //
  37. #include "always.h"
  38. #include "wwdebug.h"
  39. #include "mutex.h"
  40. #include <malloc.h>
  41. #include <stddef.h> //size_t & ptrdiff_t definition
  42. #include <string.h>
  43. ///////////////////////////////////////////////////////////////////////////////
  44. // Forward Declarations
  45. //
  46. class FastFixedAllocator; //Allocates and deletes items of a fixed size.
  47. class FastAllocatorGeneral; //Allocates and deletes items of any size. Can use as a fast replacement for global new/delete.
  48. ///////////////////////////////////////////////////////////////////////////////
  49. // StackAllocator
  50. //
  51. // Introduction:
  52. // This templated class allows you to allocate a dynamically sized temporary
  53. // block of memory local to a function in a way that causes it to use some
  54. // stack space instead of using the (very slow) malloc function. You don't
  55. // want to call malloc/new to allocate temporary blocks of memory when speed
  56. // is important. This class is only practical if you are allocating arrays of
  57. // objects (especially smaller objects). If you have a class whose size is
  58. // 40K, you aren't going to be able to put even one of them on the stack.
  59. // If you don't need an array but instead just need a single object, then you
  60. // can simply create your object on the stack and be done with it. However,
  61. // there are some times when you need a temporary array of objects (or just
  62. // an array of chars or pointers) but don't know the size beforehand. That's
  63. // where this class is useful.
  64. //
  65. // Parameters:
  66. // The class takes three templated parameters: T, nStackCount, bConstruct.
  67. // T -- The type of object being allocated. Examples include char,
  68. // cRZString, int*, cRZRect*.
  69. // nStackCount -- How many items to allocate on the stack before switching
  70. // to a heap allocation. Note that if you want to write
  71. // portable code, you need to use no more than about 2K
  72. // of stack space. So make sure nStackCount*sizeof(T) < 2048.
  73. // bConstruct -- This is normally 1, but setting it to 0 is a hint to the
  74. // compiler that you are constructing a type that has no
  75. // constructor. Testing showed that the VC++ compiler wasn't
  76. // completely able to optimize on its own. In particular, it
  77. // was smart enough to remove the while loop, but not smart
  78. // enough to remore the pTArrayEnd assignment.
  79. //
  80. // Benchmarks:
  81. // Testing one one machine showed that allocating and freeing a block of
  82. // 2048 bytes via malloc/free took 8700 and 8400 clock ticks respectively.
  83. // Using this stack allocator to do the same thing tooko 450 and 375 clock
  84. // ticks respectively.
  85. //
  86. // Usage and examples:
  87. // Since we are using a local allocator and not overloading global or class
  88. // operator new, you have to directory call StackAllocator::New instead
  89. // of operator new. So instead of saying:
  90. // SomeStruct* pStructArray = new SomeStruct[13];
  91. // you say:
  92. // SomeStruct* pStructArray = stackAllocator.New(13);
  93. //
  94. // void Example(int nSize){
  95. // StackAllocator<char, 512> stackAllocator; //Create an instance
  96. // char* pArray = stackAllocator.New(nSize); //Allocate memory, it will auto-freed.
  97. // memset(pArray, 0, nSize*sizeof(char)); //Do something with the memory.
  98. // }
  99. //
  100. // void Example(int nSize){
  101. // StackAllocator<int*, 512, 0> stackAllocator; //Create an instance. We use the 'construct' hint feature here.
  102. // int** pArray = stackAllocator.New(nSize); //Allocate memory.
  103. // memset(pArray, 0, nSize*sizeof(int*)); //Do something with the memory.
  104. // stackAllocator.Delete(pArray); //In this example, we explicity free the memory.
  105. // }
  106. //
  107. // void Example(int nSize){
  108. // StackAllocator<cRZRect, 200> stackAllocator; //Create an instance
  109. // cRZRect* pRectArray = stackAllocator.New(nSize); //Allocate memory, it will auto-freed.
  110. // pRectArray[0].SetRect(0,0,1,1); //Do something with the memory.
  111. // }
  112. //
  113. // void Example(int nSize){
  114. // StackAllocator<char, 200> stackAllocator; //Create an instance
  115. // char* pArray = stackAllocator.New(nSize); //Allocate memory.
  116. // char* pArray2 = stackAllocator.New(nSize); //Allocate some additional memory.
  117. // memset(pArray, 0, nSize*sizeof(char)); //Do something with the memory.
  118. // stackAllocator.Delete(pArray); //Delete the memory
  119. // pArray = stackAllocator.New(nSize*2); //Allocate some new memory. We'll let the allocator free it.
  120. // memset(pArray, 0, nSize*2*sizeof(char)); //Do something with the new memory.
  121. // stackAllocator.Delete(pArray2); //Delete the additional memory.
  122. // }
  123. //
  124. template<class T, int nStackCount, int bConstruct=1>
  125. class StackAllocator{
  126. public:
  127. StackAllocator() : mnAllocCount(-1), mpTHeap(NULL){}
  128. ~StackAllocator(){
  129. if(mnAllocCount != -1){ //If there is anything to do...
  130. if(mpTHeap)
  131. delete mpTHeap;
  132. else{
  133. if(bConstruct){ //Since this constant, the comparison gets optimized away.
  134. T* pTArray = (T*)mTArray;
  135. const T* const pTArrayEnd = pTArray + mnAllocCount;
  136. while(pTArray < pTArrayEnd){
  137. pTArray->~T(); //Call the destructor on the object directly.
  138. ++pTArray;
  139. }
  140. }
  141. }
  142. }
  143. }
  144. T* New(unsigned nCount){
  145. if(mnAllocCount == -1){
  146. mnAllocCount = nCount;
  147. if(nCount < nStackCount){ //If the request is small enough to come from the stack...
  148. //We call the constructors of all the objects here.
  149. if(bConstruct){ //Since this constant, the comparison gets optimized away.
  150. T* pTArray = (T*)mTArray;
  151. const T* const pTArrayEnd = pTArray + nCount;
  152. while(pTArray < pTArrayEnd){
  153. new(pTArray)T; //Use the placement operator new. This simply calls the constructor
  154. ++pTArray; //of T with 'this' set to the input address. Note that we don't put
  155. } //a '()' after the T this is because () causes trivial types like int
  156. } //and class* to be assigned zero/NULL. We don't want that.
  157. return (T*)mTArray;
  158. } //Else the request is too big. So let's use (the slower) operator new.
  159. return (mpTHeap = new T[nCount]); //The compiler will call the constructors here.
  160. } //Else we are being used. Let's be nice and allocate something anyway.
  161. return new T[nCount];
  162. }
  163. void Delete(T* pT){
  164. if(pT == (T*)mTArray){ //If the allocation came from our stack...
  165. if(bConstruct){ //Since this constant, the comparison gets optimized away.
  166. T* pTArray = (T*)mTArray;
  167. const T* const pTArrayEnd = pTArray + mnAllocCount;
  168. while(pTArray < pTArrayEnd){
  169. pTArray->~T(); //Call the destructor on the object directly.
  170. ++pTArray;
  171. }
  172. }
  173. mnAllocCount = -1;
  174. }
  175. else if(pT == mpTHeap){ //If the allocation came from our heap...
  176. delete[] mpTHeap; //The compiler will call the destructors here.
  177. mpTHeap = NULL; //We clear these out so that we can possibly
  178. mnAllocCount = -1; // use the allocator again.
  179. }
  180. else //Else the allocation came from the external heap.
  181. delete[] pT;
  182. }
  183. protected:
  184. int mnAllocCount; //Count of objects allocated. -1 means that nothing is allocated. We don't use zero because zero is a legal allocation count in C++.
  185. T* mpTHeap; //This is normally NULL, but gets used of the allocation request is too high.
  186. char mTArray[nStackCount*sizeof(T)]; //This is our stack memory.
  187. };
  188. ///////////////////////////////////////////////////////////////////////////////
  189. ///////////////////////////////////////////////////////////////////////////////
  190. // class FastFixedAllocator
  191. //
  192. class FastFixedAllocator
  193. {
  194. public:
  195. FastFixedAllocator(unsigned int n=0);
  196. ~FastFixedAllocator();
  197. void Init(unsigned int n); //Useful for setting allocation size *after* construction,
  198. //but before first use.
  199. void* Alloc();
  200. void Free(void* pAlloc);
  201. unsigned Get_Heap_Size() const { return TotalHeapSize; }
  202. unsigned Get_Allocated_Size() const { return TotalAllocatedSize; }
  203. unsigned Get_Allocation_Count() const { return TotalAllocationCount; }
  204. protected:
  205. struct Link
  206. {
  207. Link* next;
  208. };
  209. struct Chunk
  210. {
  211. enum {
  212. size = 8*1024-16
  213. };
  214. Chunk* next;
  215. char mem[size];
  216. };
  217. Chunk* chunks;
  218. unsigned int esize;
  219. unsigned TotalHeapSize;
  220. unsigned TotalAllocatedSize;
  221. unsigned TotalAllocationCount;
  222. Link* head;
  223. void grow();
  224. };
  225. // ----------------------------------------------------------------------------
  226. //
  227. //
  228. //
  229. // ----------------------------------------------------------------------------
  230. WWINLINE void* FastFixedAllocator::Alloc()
  231. {
  232. TotalAllocationCount++;
  233. TotalAllocatedSize+=esize;
  234. if (head==0) {
  235. grow();
  236. }
  237. Link* p = head;
  238. head = p->next;
  239. return p;
  240. }
  241. // ----------------------------------------------------------------------------
  242. //
  243. //
  244. //
  245. // ----------------------------------------------------------------------------
  246. WWINLINE void FastFixedAllocator::Free(void* pAlloc)
  247. {
  248. TotalAllocationCount--;
  249. TotalAllocatedSize-=esize;
  250. Link* p = static_cast<Link*>(pAlloc);
  251. p->next = head;
  252. head = p;
  253. }
  254. // ----------------------------------------------------------------------------
  255. //
  256. //
  257. //
  258. // ----------------------------------------------------------------------------
  259. WWINLINE FastFixedAllocator::FastFixedAllocator(unsigned int n) : esize(1), TotalHeapSize(0), TotalAllocatedSize(0), TotalAllocationCount(0)
  260. {
  261. head = 0;
  262. chunks = 0;
  263. Init(n);
  264. }
  265. // ----------------------------------------------------------------------------
  266. //
  267. //
  268. //
  269. // ----------------------------------------------------------------------------
  270. WWINLINE FastFixedAllocator::~FastFixedAllocator()
  271. {
  272. Chunk* n = chunks;
  273. while(n){
  274. Chunk* p = n;
  275. n = n->next;
  276. delete p;
  277. }
  278. }
  279. // ----------------------------------------------------------------------------
  280. //
  281. //
  282. //
  283. // ----------------------------------------------------------------------------
  284. WWINLINE void FastFixedAllocator::Init(unsigned int n)
  285. {
  286. esize = (n<sizeof(Link*) ? sizeof(Link*) : n);
  287. }
  288. // ----------------------------------------------------------------------------
  289. //
  290. //
  291. //
  292. // ----------------------------------------------------------------------------
  293. WWINLINE void FastFixedAllocator::grow()
  294. {
  295. Chunk* n = new Chunk;
  296. n->next = chunks;
  297. chunks = n;
  298. TotalHeapSize+=sizeof(Chunk);
  299. const int nelem = Chunk::size/esize;
  300. char* start = n->mem;
  301. char* last = &start[(nelem-1)*esize];
  302. for(char* p = start; p<last; p+=esize)
  303. reinterpret_cast<Link*>(p)->next = reinterpret_cast<Link*>(p+esize);
  304. reinterpret_cast<Link*>(last)->next = 0;
  305. head = reinterpret_cast<Link*>(start);
  306. }
  307. ///////////////////////////////////////////////////////////////////////////////
  308. ///////////////////////////////////////////////////////////////////////////////
  309. // class FastAllocatorGeneral
  310. //
  311. // This class works by putting sizes into fixed size buckets. Each fixed size
  312. // bucket is a FastFixedAllocator.
  313. //
  314. class FastAllocatorGeneral
  315. {
  316. enum {
  317. MAX_ALLOC_SIZE=2048,
  318. ALLOC_STEP=16
  319. };
  320. public:
  321. FastAllocatorGeneral();
  322. void* Alloc(unsigned int n);
  323. void Free(void* pAlloc);
  324. void* Realloc(void* pAlloc, unsigned int n);
  325. unsigned Get_Total_Heap_Size();
  326. unsigned Get_Total_Allocated_Size();
  327. unsigned Get_Total_Allocation_Count();
  328. unsigned Get_Total_Actual_Memory_Usage() { return ActualMemoryUsage; }
  329. static FastAllocatorGeneral* Get_Allocator();
  330. protected:
  331. FastFixedAllocator allocators[MAX_ALLOC_SIZE/ALLOC_STEP];
  332. FastCriticalSectionClass CriticalSections[MAX_ALLOC_SIZE/ALLOC_STEP];
  333. bool MemoryLeakLogEnabled;
  334. unsigned AllocatedWithMalloc;
  335. unsigned AllocatedWithMallocCount;
  336. unsigned ActualMemoryUsage;
  337. };
  338. ///////////////////////////////////////////////////////////////////////////////
  339. WWINLINE unsigned FastAllocatorGeneral::Get_Total_Heap_Size()
  340. {
  341. int size=AllocatedWithMalloc;
  342. for (int i=0;i<MAX_ALLOC_SIZE/ALLOC_STEP;++i) {
  343. FastCriticalSectionClass::LockClass lock(CriticalSections[i]);
  344. size+=allocators[i].Get_Heap_Size();
  345. }
  346. return size;
  347. }
  348. WWINLINE unsigned FastAllocatorGeneral::Get_Total_Allocated_Size()
  349. {
  350. int size=AllocatedWithMalloc;
  351. for (int i=0;i<MAX_ALLOC_SIZE/ALLOC_STEP;++i) {
  352. FastCriticalSectionClass::LockClass lock(CriticalSections[i]);
  353. size+=allocators[i].Get_Allocated_Size();
  354. }
  355. return size;
  356. }
  357. WWINLINE unsigned FastAllocatorGeneral::Get_Total_Allocation_Count()
  358. {
  359. int count=AllocatedWithMallocCount;
  360. for (int i=0;i<MAX_ALLOC_SIZE/ALLOC_STEP;++i) {
  361. FastCriticalSectionClass::LockClass lock(CriticalSections[i]);
  362. count+=allocators[i].Get_Allocation_Count();
  363. }
  364. return count;
  365. }
  366. // ----------------------------------------------------------------------------
  367. //
  368. //
  369. //
  370. // ----------------------------------------------------------------------------
  371. WWINLINE void* FastAllocatorGeneral::Alloc(unsigned int n)
  372. {
  373. void* pMemory;
  374. static int re_entrancy=0;
  375. re_entrancy++;
  376. //We actually allocate n+4 bytes. We store the # allocated
  377. //in the first 4 bytes, and return the ptr to the rest back
  378. //to the user.
  379. n += sizeof(unsigned int);
  380. #ifdef MEMORY_OVERWRITE_TEST
  381. n+=sizeof(unsigned int);
  382. #endif
  383. if (re_entrancy==1) {
  384. ActualMemoryUsage+=n;
  385. }
  386. if (n<MAX_ALLOC_SIZE) {
  387. int index=(n)/ALLOC_STEP;
  388. {
  389. FastCriticalSectionClass::LockClass lock(CriticalSections[index]);
  390. pMemory = allocators[index].Alloc();
  391. }
  392. }
  393. else {
  394. if (re_entrancy==1) {
  395. AllocatedWithMalloc+=n;
  396. AllocatedWithMallocCount++;
  397. }
  398. pMemory = ::malloc(n);
  399. }
  400. #ifdef MEMORY_OVERWRITE_TEST
  401. *((unsigned int*)((char*)pMemory+n)-1)=0xabbac0de;
  402. #endif
  403. re_entrancy--;
  404. *((unsigned int*)pMemory) = n; //Write modified (augmented by 4) count into first four bytes.
  405. return ((unsigned int*)pMemory)+1; //return ptr to bytes after it back to user.
  406. }
  407. // ----------------------------------------------------------------------------
  408. //
  409. //
  410. //
  411. // ----------------------------------------------------------------------------
  412. WWINLINE void FastAllocatorGeneral::Free(void* pAlloc)
  413. {
  414. if (pAlloc) {
  415. unsigned int* n = ((unsigned int*)pAlloc)-1; //Subtract four bytes and the count is stored there.
  416. #ifdef MEMORY_OVERWRITE_TEST
  417. WWASSERT(*((unsigned int*)((char*)n+*n)-1)==0xabbac0de);
  418. #endif
  419. unsigned size=*n;
  420. ActualMemoryUsage-=size;
  421. if (size<MAX_ALLOC_SIZE) {
  422. int index=size/ALLOC_STEP;
  423. FastCriticalSectionClass::LockClass lock(CriticalSections[index]);
  424. allocators[index].Free(n);
  425. }
  426. else {
  427. AllocatedWithMallocCount--;
  428. AllocatedWithMalloc-=size;
  429. ::free(n);
  430. }
  431. }
  432. }
  433. //ANSI C requires:
  434. // (1) realloc(NULL, newsize) is equivalent to malloc(newsize).
  435. // (2) realloc(pblock, 0) is equivalent to free(pblock) (except that NULL is returned).
  436. // (3) if the realloc() fails, the object pointed to by pblock is left unchanged.
  437. //
  438. WWINLINE void* FastAllocatorGeneral::Realloc(void* pAlloc, unsigned int n){
  439. if(n){
  440. void* const pNewAlloc = Alloc(n); //Allocate the new memory. This never fails.
  441. if(pAlloc){
  442. n = *(((unsigned int*)pAlloc)-1); //Subtract four bytes and the count is stored there.
  443. ::memcpy(pNewAlloc, pAlloc, n); //Copy the old memory into the new memory.
  444. Free(pAlloc); //Delete the old memory.
  445. }
  446. return pNewAlloc;
  447. }
  448. Free(pAlloc);
  449. return NULL;
  450. }
  451. ///////////////////////////////////////////////////////////////////////////////
  452. // FastSTLAllocator
  453. //
  454. // An STL allocator based on a simple fixed size allocator is not going to
  455. // buy you the performance you really want. This is because STL containers
  456. // allocate not just objects of the size of the container, but other objects
  457. // as well. For example, the STL "list" class generally allocates item nodes
  458. // and not items themselves. The STL vector class usually allocates in chunks
  459. // of contiguous items. So your allocator will probably want to have a bucket
  460. // system whereby it maintains buckets for integral sizes.
  461. //
  462. #ifdef _MSC_VER
  463. //VC++ continues to be the one compiler that lacks the ability to compile
  464. //standard C++. So we define a version of the STL allocator specifically
  465. //for VC++, and let other compilers use a standard allocator template.
  466. template <class T>
  467. struct FastSTLAllocator{
  468. typedef size_t size_type; //basically, "unsigned int"
  469. typedef ptrdiff_t difference_type; //basically, "int"
  470. typedef T* pointer;
  471. typedef const T* const_pointer;
  472. typedef T& reference;
  473. typedef const T& const_reference;
  474. typedef T value_type;
  475. T* address(T& t) const { return (&t); } //These two are slightly strange but
  476. const T* address(const T& t) const { return (&t); } //required functions. Just do it.
  477. static T* allocate(size_t n, const void* =NULL) { return (T*)generalAllocator.Alloc(n*sizeof(T)); }
  478. static void construct(T* ptr, const T& value) { new(ptr) T(value); }
  479. static void deallocate(void* ptr, size_t /*n*/) { generalAllocator.Free(ptr); }
  480. static void destroy(T* ptr) { ptr->~T(); }
  481. static size_t max_size() { return (size_t)-1; }
  482. //This _Charalloc is required by VC++5 since it VC++5 predates
  483. //the language standardization. Allocator behaviour is one of the
  484. //last things to have been hammered out. Important note: If you
  485. //decide to write your own fast allocator, containers will allocate
  486. //random objects through this function but delete them through
  487. //the above delallocate() function. So your version of deallocate
  488. //should *not* assume that it will only be given T objects to delete.
  489. char* _Charalloc(size_t n){ return (char*)::generalAllocator.Alloc(n*sizeof(char)); }
  490. };
  491. #else
  492. //This is a C++ language standard allocator. Most C++ compilers after 1999
  493. //other than Microsoft C++ compile this fine. Otherwise. you might be able
  494. //to use the same allocator as VC++ uses above.
  495. template <class T>
  496. class FastSTLAllocator{
  497. public:
  498. typedef size_t size_type;
  499. typedef ptrdiff_t difference_type;
  500. typedef T* pointer;
  501. typedef const T* const_pointer;
  502. typedef T& reference;
  503. typedef const T& const_reference;
  504. typedef T value_type;
  505. template <class T1> struct rebind {
  506. typedef FastSTLAllocator<T1> other;
  507. };
  508. FastSTLAllocator() {}
  509. FastSTLAllocator(const FastSTLAllocator&) {}
  510. template <class T1> FastSTLAllocator(const FastSTLAllocator<T1>&) {}
  511. ~FastSTLAllocator() {}
  512. pointer address(reference x) const { return &x; }
  513. const_pointer address(const_reference x) const { return &x; }
  514. T* allocate(size_type n, const void* = NULL) { return n != 0 ? static_cast<T*>(generalAllocator.Alloc(n*sizeof(T))) : NULL; }
  515. void deallocate(pointer p, size_type n) { generalAllocator.Free(p); }
  516. size_type max_size() const { return size_t(-1) / sizeof(T); }
  517. void construct(pointer p, const T& val) { new(p) T(val); }
  518. void destroy(pointer p) { p->~T(); }
  519. };
  520. #endif
  521. template<class T>
  522. WWINLINE bool operator==(const FastSTLAllocator<T>&, const FastSTLAllocator<T>&) { return true; }
  523. template<class T>
  524. WWINLINE bool operator!=(const FastSTLAllocator<T>&, const FastSTLAllocator<T>&) { return false; }
  525. ///////////////////////////////////////////////////////////////////////////////
  526. /*
  527. ///////////////////////////////////////////////////////////////////////////////
  528. // Example usage of fast allocators in STL.
  529. //
  530. ///////////////////////////////////////////////////////////////////////////////
  531. #include <stdio.h>
  532. #include <vector>
  533. #include <list>
  534. #include <deque>
  535. #include <queue>
  536. #include <stack>
  537. #include <set>
  538. #include <map>
  539. #include <string>
  540. #include <memory>
  541. #include <hash_set> //Uncomment this if you have hash containers available.
  542. #include <hash_map>
  543. using namespace std;
  544. ///////////////////////////////////////////////////////////////////////////////
  545. // Here's how you declare a custom allocator for every regular STL container class:
  546. //
  547. typedef vector<int, FastSTLAllocator<int> > IntArray;
  548. typedef list<int, FastSTLAllocator<int> > IntList;
  549. typedef deque<int, FastSTLAllocator<int> > IntDequeue;
  550. typedef queue<int, deque<int, FastSTLAllocator<int> > > IntQueue;
  551. typedef priority_queue<int, vector<int, FastSTLAllocator<int> > > IntPriorityQueue;
  552. typedef stack<int, deque<int, FastSTLAllocator<int> > > IntStack;
  553. typedef map<int, int, less<int>, FastSTLAllocator<int> > IntMap;
  554. typedef multimap<int, int, less<int>, FastSTLAllocator<int> > IntMultiMap;
  555. typedef set<int, less<int>, FastSTLAllocator<int> > IntSet;
  556. typedef multiset<int, less<int>, FastSTLAllocator<int> > IntMultiSet;
  557. //If you have the hashing containers available, here's how you do it:
  558. typedef hash_map<int, int, hash<int>, equal_to<int>, FastSTLAllocator<int> > IntHashMap;
  559. typedef hash_multimap<int, int, hash<int>, equal_to<int>, FastSTLAllocator<int> > IntHashMultiMap;
  560. typedef hash_set<int, hash<int>, equal_to<int>, FastSTLAllocator<int> > IntHashSet;
  561. typedef hash_multiset<int, hash<int>, equal_to<int>, FastSTLAllocator<int> > IntHashMultiSet;
  562. typedef basic_string<char, char_traits<char>, FastSTLAllocator<char> > CharString;
  563. //bitset and valarray don't allow custom allocators.
  564. ///////////////////////////////////////////////////////////////////////////////
  565. void main(){
  566. IntArray intArray;
  567. intArray.push_back(3);
  568. intArray.pop_back();
  569. IntList intList;
  570. intList.push_back(3);
  571. intList.pop_back();
  572. IntDequeue intDequeue;
  573. intDequeue.push_back(3);
  574. intDequeue.pop_back();
  575. IntQueue intQueue;
  576. intQueue.push(3);
  577. intQueue.pop();
  578. IntPriorityQueue intPriorityQueue;
  579. intPriorityQueue.push(3);
  580. intPriorityQueue.pop();
  581. IntStack intStack;
  582. intStack.push(3);
  583. intStack.pop();
  584. IntMap intMap;
  585. intMap.insert(pair<int,int>(3,3));
  586. intMap.erase(3);
  587. IntMultiMap intMultiMap;
  588. intMultiMap.insert(pair<int,int>(3,3));
  589. intMultiMap.erase(3);
  590. IntSet intSet;
  591. intSet.insert(3);
  592. intSet.erase(3);
  593. IntMultiSet intMultiSet;
  594. intMultiSet.insert(3);
  595. intMultiSet.erase(3);
  596. IntHashMap intHashMap;
  597. intHashMap.insert(3);
  598. intHashMap.erase(3);
  599. IntHashMultiMap intHashMultiMap;
  600. intHashMultiMap.insert(3);
  601. intHashMultiMap.erase(3);
  602. IntHashSet intHashSet;
  603. intHashSet.insert(3);
  604. intHashSet.erase(3);
  605. IntHashMultiSet intHashMultiSet;
  606. intHashMultiSet.insert(3);
  607. intHashMultiSet.erase(3);
  608. CharString charString;
  609. charString.append(1, '3');
  610. charString.erase(charString.length()-1);
  611. //Shutdown
  612. printf("\nDone. Press the 'any' key\n");
  613. getchar();
  614. }
  615. */
  616. #endif //sentry