Eneboo - Documentación para desarrolladores
|
00001 /* -*- C++ -*- */ 00002 00003 #ifndef _BATCHHEAP_H_ 00004 #define _BATCHHEAP_H_ 00005 00006 #include <assert.h> 00007 00008 00009 template <class SuperHeap> 00010 class MultiMalloc : public SuperHeap { 00011 public: 00012 // Sets ptr to a list of up to num objects of size sz 00013 // and returns how many free objects ptr points to. 00014 int multimalloc (int num, size_t sz, void *& ptr) 00015 { 00016 int i = 0; 00017 ptr = (freeObject *) SuperHeap::malloc (sz); 00018 freeObject * p = (freeObject *) ptr; 00019 if (ptr != NULL) { 00020 for (i = 1; i < num; i++) { 00021 p->next = (freeObject *) SuperHeap::malloc (sz); 00022 if (p->next == NULL) 00023 break; 00024 p = p->next; 00025 } 00026 p->next = NULL; 00027 } 00028 return i; 00029 } 00030 00031 // Frees all num items pointed to by ptr 00032 // and sets ptr to NULL. 00033 void multifree (int num, void *& ptr) 00034 { 00035 freeObject * p; 00036 freeObject * prev = (freeObject *) ptr; 00037 for (int i = 0; i < num; i++) { 00038 p = prev->next; 00039 SuperHeap::free (prev); 00040 prev = p; 00041 } 00042 ptr = NULL; 00043 } 00044 00045 private: 00046 00047 class freeObject { 00048 public: 00049 freeObject * next; 00050 }; 00051 00052 00053 }; 00054 00055 00056 template <int BatchNumber, class SuperHeap> 00057 class BatchHeap : public SuperHeap { 00058 public: 00059 00060 BatchHeap (void) 00061 : nObjects (0) 00062 { 00063 freeList[0] = NULL; 00064 freeList[1] = NULL; 00065 } 00066 00067 00068 ~BatchHeap (void) { 00069 if (nObjects <= BatchNumber) { 00070 SuperHeap::multifree (nObjects, (void *&) freeList[0]); 00071 } else { 00072 SuperHeap::multifree (BatchNumber, (void *&) freeList[0]); 00073 SuperHeap::multifree (nObjects - BatchNumber, (void *&) freeList[1]); 00074 } 00075 } 00076 00077 inline void * malloc (size_t sz) { 00078 if (nObjects == 0) { 00079 // Obtain BatchNumber objects if we're out. 00080 nObjects = SuperHeap::multimalloc (BatchNumber, sz, (void *&) freeList[0]); 00081 } 00082 assert (nObjects >= 1); 00083 freeObject * ptr; 00084 if (nObjects > BatchNumber) { 00085 freeObject *& head = freeList[1]; 00086 ptr = head; 00087 nObjects--; 00088 head = head->next; 00089 return (void *) ptr; 00090 } else { 00091 freeObject *& head = freeList[0]; 00092 ptr = head; 00093 nObjects--; 00094 head = head->next; 00095 return (void *) ptr; 00096 } 00097 } 00098 00099 inline void free (void * ptr) { 00100 if (nObjects <= BatchNumber) { 00101 freeObject *& head = freeList[0]; 00102 ((freeObject *) ptr)->next = head; 00103 head = (freeObject *) ptr; 00104 } else { 00105 freeObject *& head = freeList[1]; 00106 ((freeObject *) ptr)->next = head; 00107 head = (freeObject *) ptr; 00108 } 00109 nObjects++; 00110 if (nObjects == 2 * BatchNumber) { 00111 // Free half of them. 00112 assert (freeList[1] != NULL); 00113 SuperHeap::multifree (BatchNumber, (void *&) freeList[1]); 00114 } 00115 } 00116 00117 private: 00118 00119 class freeObject { 00120 public: 00121 freeObject * next; 00122 }; 00123 00124 int nObjects; 00125 00126 // The first free list holds the first BatchNumber objects, 00127 // while the second free list holds the rest. 00128 freeObject * freeList[2]; 00129 }; 00130 00131 #endif