MemoryManager.cpp

Go to the documentation of this file.
00001 /*
00002 Copyright (C) 2002-2004 The Pentagram team
00003 
00004 This program is free software; you can redistribute it and/or
00005 modify it under the terms of the GNU General Public License
00006 as published by the Free Software Foundation; either version 2
00007 of the License, or (at your option) any later version.
00008 
00009 This program is distributed in the hope that it will be useful,
00010 but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012 GNU General Public License for more details.
00013 
00014 You should have received a copy of the GNU General Public License
00015 along with this program; if not, write to the Free Software
00016 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00017 */
00018 
00019 #include "pent_include.h"
00020 
00021 #include "MemoryManager.h"
00022 
00023 #include "SegmentedAllocator.h"
00024 
00025 MemoryManager* MemoryManager::memorymanager = 0;
00026 
00027 MemoryManager::MemoryManager()
00028 {
00029         assert(memorymanager == 0);
00030         memorymanager = this;
00031 
00033         allocatorCount = 2;
00034         // Tune these with averages from MemoryManager::MemInfo when needed
00035         allocators[0] = new SegmentedAllocator(192, 8500);
00036         allocators[1] = new SegmentedAllocator(4224, 25);
00037 
00038         Pentagram::setAllocationFunctions(MemoryManager::allocate,
00039                                                                           MemoryManager::deallocate);
00040 }
00041 
00042 MemoryManager::~MemoryManager()
00043 {
00044         memorymanager = 0;
00045 
00046         Pentagram::setAllocationFunctions(malloc, free);
00047         delete allocators[0];
00048         delete allocators[1];
00049 }
00050 
00051 void * MemoryManager::_allocate(size_t size)
00052 {
00053         int i;
00054         // get the memory from the first allocator that can hold "size"
00055         for (i = 0; i < allocatorCount; ++i)
00056         {
00057                 if (allocators[i]->getCapacity() >= size)
00058                 {
00059                         return allocators[i]->allocate(size);
00060                 }
00061         }
00062 
00063         // else
00064         void * ptr = malloc(size);
00065 #ifdef DEBUG
00066         con.Printf("MemoryManager::allocate - Allocated %d bytes to 0x%X\n", size, ptr);
00067 #endif
00068 
00069         return ptr;
00070 }
00071 
00072 void MemoryManager::_deallocate(void * ptr)
00073 {
00074         Pool * p;
00075         int i;
00076         for (i = 0; i < allocatorCount; ++i)
00077         {
00078                 p = allocators[i]->findPool(ptr);
00079                 if (p)
00080                 {
00081                         p->deallocate(ptr);
00082                         return;
00083                 }
00084         }
00085 
00086 #ifdef DEBUG
00087         con.Printf("MemoryManager::deallocate - deallocating memory at 0x%X\n", ptr);
00088 #endif
00089         // Pray!
00090         free(ptr);
00091 }
00092 
00093 void MemoryManager::freeResources()
00094 {
00095         int i;
00096         for (i = 0; i < allocatorCount; ++i)
00097         {
00098                 allocators[i]->freeResources();
00099         }
00100 }
00101 
00102 void MemoryManager::ConCmd_MemInfo(const Console::ArgvType &argv)
00103 {
00104         MemoryManager * mm = MemoryManager::get_instance();
00105         int i, count;
00106 
00107         if (!mm)
00108                 return;
00109 
00110         count = mm->getAllocatorCount();
00111 
00112         pout << "Allocators: " << count << std::endl;
00113         for (i = 0; i < count; ++i)
00114         {
00115                 pout << " Allocator " << i << ": " << std::endl;
00116                 mm->getAllocator(i)->printInfo();
00117                 pout << "==============" << std::endl;
00118         }
00119 }
00120 
00121 #ifdef DEBUG
00122 
00123 #include <SDL.h>
00124 // Test classes purely here to check the speed of Allocators vs. normal allocation
00125 class TestClassBase
00126 {
00127 public:
00128         TestClassBase()
00129         {
00130                 next = 0;
00131         }
00132 
00133         virtual ~TestClassBase()
00134         {
00135         }
00136 
00137         void setNext(TestClassBase * n)
00138         {
00139                 n->next = next;
00140                 next = n;
00141         }
00142 
00143         void removeNext()
00144         {
00145                 TestClassBase * n;
00146                 if (! next)
00147                         return;
00148                 n = next;
00149                 next = n->next;
00150                 delete n;
00151         }
00152 
00153         ENABLE_RUNTIME_CLASSTYPE();
00154 
00155         TestClassBase *next;
00156         int arr[32];
00157 };
00158 
00159 DEFINE_RUNTIME_CLASSTYPE_CODE_BASE_CLASS(TestClassBase);
00160 
00161 class TestClassOne: public TestClassBase
00162 {
00163 public:
00164         TestClassOne()
00165         {
00166         }
00167 
00168         virtual ~TestClassOne()
00169         {
00170         }
00171 
00172         ENABLE_RUNTIME_CLASSTYPE();
00173 };
00174 
00175 DEFINE_RUNTIME_CLASSTYPE_CODE(TestClassOne, TestClassBase);
00176 
00177 
00178 class TestClassTwo: public TestClassBase
00179 {
00180 public:
00181         TestClassTwo()
00182         {
00183         }
00184 
00185         virtual ~TestClassTwo()
00186         {
00187         }
00188 
00189         ENABLE_RUNTIME_CLASSTYPE();
00190         ENABLE_CUSTOM_MEMORY_ALLOCATION();
00191 };
00192 
00193 DEFINE_RUNTIME_CLASSTYPE_CODE(TestClassTwo, TestClassBase);
00194 DEFINE_CUSTOM_MEMORY_ALLOCATION(TestClassTwo);
00195 
00196 void MemoryManager::ConCmd_test(const Console::ArgvType &argv)
00197 {
00198         // Just some numbers of classes to allocate and free
00199         int a[10] = {1000, 1231, 2423, 1233, 3213, 2554, 1123, 2432, 3311, 1022};
00200         int b[10] = {900, 1111, 2321, 1000, 1321, 1432, 1123, 2144, 2443, 0};
00201         int i, j, repeat;
00202         uint32 pooled, unpooled;
00203         TestClassBase * t;
00204 
00205         t = new TestClassBase();
00206 
00207         unpooled = SDL_GetTicks();
00208         for (repeat=0; repeat < 100; ++repeat)
00209         {
00210                 for (i=0; i < 10; ++i)
00211                 {
00212                         // allocate
00213                         for (j=0; j < a[i]; ++j)
00214                         {
00215                                 t->setNext(new TestClassOne());
00216                         }
00217                         // free
00218                         for (j=0; j < b[i]; ++j)
00219                         {
00220                                 t->removeNext();
00221                         }
00222                 }
00223                 while (t->next)
00224                 {
00225                         t->removeNext();
00226                 }
00227         }
00228         unpooled = SDL_GetTicks() - unpooled;
00229 
00230         pooled = SDL_GetTicks();
00231         for (repeat=0; repeat < 100; ++repeat)
00232         {
00233                 for (i=0; i < 10; ++i)
00234                 {
00235                         // allocate
00236                         for (j=0; j < a[i]; ++j)
00237                         {
00238                                 t->setNext(new TestClassTwo());
00239                         }
00240                         // free
00241                         for (j=0; j < b[i]; ++j)
00242                         {
00243                                 t->removeNext();
00244                         }
00245                 }
00246                 while (t->next)
00247                 {
00248                         t->removeNext();
00249                 }
00250         }
00251         pooled = SDL_GetTicks() - pooled;
00252 
00253         delete t;
00254 
00255         con.Printf("Unpooled Allocation: %d ms\nPooled Allocation: %d ms\n", unpooled, pooled);
00256 }
00257 
00258 #else
00259 void MemoryManager::ConCmd_test(const Console::ArgvType &argv)
00260 {
00261 }
00262 
00263 #endif
00264 

Generated on Fri Jul 27 22:27:25 2007 for pentagram by  doxygen 1.4.7