00001 #ifdef CH_LANG_CC 00002 /* 00003 * _______ __ 00004 * / ___/ / ___ __ _ / / ___ 00005 * / /__/ _ \/ _ \/ V \/ _ \/ _ \ 00006 * \___/_//_/\___/_/_/_/_.__/\___/ 00007 * Please refer to Copyright.txt, in Chombo's root directory. 00008 */ 00009 #endif 00010 00011 #ifndef _POOL_H_ 00012 #define _POOL_H_ 00013 00014 #include <cstdlib> 00015 #include <list> 00016 00017 #include "Vector.H" 00018 #include "BaseNamespaceHeader.H" 00019 00020 class Pool; 00021 typedef std::list<Pool*> PoolList; 00022 00023 /// Pool is a class to optimize memory allocation. 00024 /** 00025 Pool is a class to optimize memory allocation. It is specialized to 00026 allocate fixed size chunks of memory specified by ptrSize in the 00027 constructor. Its operation is analogous to malloc, not new. It 00028 does not initialize the memory in any way. The constructor can 00029 optionally specify an initial pool size, and memory alignment. The 00030 pool size will grow as needed by calling ::new. The pool size never 00031 shrinks. Memory will be reclaimed at ~Pool(). The units of poolSize 00032 are number-of-ptrSize-chunks. The units of alignment are bytes. 00033 00034 Pool can only be used for objects of fixed size. Typically used in 00035 situations where a class or struct is being constantly constructed and 00036 deleted. Objects returned by value from functions, elements in a database, 00037 etc. Pool's tend to be allocated statically. 00038 00039 (from Copier.cpp) 00040 \code 00041 00042 // static data member s_motionIemPool getting constructed 00043 Pool Copier::s_motionItemPool(sizeof(MotionItem), "Copier::MotionItem"); 00044 00045 // note the use of a 'placement new' 00046 MotionItem* item = new (s_motionItemPool.getPtr()) MotionItem(fromdi, todi, box); 00047 00048 // if your object does requires it's destructor to be called. 00049 item->~MotionItem(); 00050 00051 // then return the memory chunk to your pool 00052 s_motionItemPool.returnPtr(item) 00053 00054 \endcode 00055 00056 Technical note 00057 In the event of multi-threading Chombo, we will have to make 00058 pool access serialized (locks, single thread access, etc) or implement a 00059 fast lock-free version, or go back to new/delete and let the OS be clever 00060 again about memory management. 00061 00062 */ 00063 class Pool 00064 { 00065 public: 00066 /// 00067 /** 00068 @param a_ptrSize Size of fixed memory allocations needed 00069 00070 @param a_poolSize Size of allocations (a_ptrSize*a_poolSize) made 00071 of the operating system. This controls the granularity of the 00072 Pool allocations. Smaller values result in less wasted memory, 00073 at the cost of more calls to the operating system for heap memory. 00074 00075 @param a_name optional name for this Pool. Used in reporting memory 00076 by the memory tracking system in Chombo. 00077 */ 00078 Pool(int a_ptrSize, 00079 const char* a_name = "unnamed", 00080 int a_poolSize = 100, 00081 int a_alignment = sizeof(int), 00082 bool a_allowUnalignedAlloc = false); 00083 00084 /// 00085 ~Pool(); 00086 00087 /// request a section of memory of ptrSize_ contiguous bytes. 00088 inline void* getPtr(); 00089 00090 /// return memory previous acquired with the getPtr() function. 00091 void returnPtr(void* a_ptr); 00092 00093 /// report how much memory this Pool is currently using. 00094 /** 00095 memUsage for a Pool only grows until Pool destruction. The Pool 00096 object has no knowledge of what pieces of memory it has parcelled out 00097 to a user, so it keeps it all available. The user is responsible for 00098 not leaking Pool memory. 00099 */ 00100 long memUsage() const; 00101 00102 /** 00103 undocumented function, call this at own risk. You must 00104 be absolutely positive that you have returned all the 00105 ptr's you've asked for, or you can have major seg faults. 00106 */ 00107 void clear(); 00108 00109 // not for public consumption. used in memory tracking code. 00110 static PoolList* m_poolList_; 00111 char m_name_[64]; 00112 00113 00114 protected: 00115 00116 00117 private: 00118 /// 00119 std::vector<char*> m_pool_; 00120 00121 /// 00122 int m_ptrSize_; 00123 00124 /// 00125 int m_poolSize_; 00126 00127 /// 00128 int m_alignment_; 00129 00130 bool m_allowUnalignedAlloc; ///< T - Allows unaligned allocations 00131 ///< (> sizof(double) if it is not 00132 ///< known how to allocate aligned 00133 ///< memory 00134 ///< F - Otherwise abort 00135 00136 /// 00137 void* m_next_; 00138 00139 /// 00140 void* getMoreMemory(); 00141 00142 void* getMore(); 00143 00144 /// 00145 /// Not implemented. Compiler will not let you copy a Pool 00146 Pool(const Pool& a_rhs); 00147 00148 /// Not implemented. Compiler will not let you copy a Pool 00149 const Pool& operator = (const Pool& a_rhs); 00150 00151 static void clearAllPools(); 00152 00153 friend void dumpmemoryatexit(); 00154 }; 00155 /// getPtr and returnPtr must be as fast as possible! 00156 00157 inline void* Pool::getPtr() 00158 { 00159 #ifdef _OPENMP 00160 return malloc(m_ptrSize_); 00161 #else 00162 if (m_next_ == 0) 00163 { 00164 m_next_ = getMoreMemory(); 00165 } 00166 00167 void* result = m_next_; // result points to first free chunk in list 00168 m_next_ = *(void**)m_next_; // point m_next_ to next free chunk in list. 00169 00170 return result; 00171 #endif 00172 } 00173 00174 00175 // Stroustrup (S. 11.5.1) says a declaration in the global scope is needed 00176 void dumpmemoryatexit(); 00177 00178 #include "BaseNamespaceFooter.H" 00179 #endif