Blender V2.61 - r43446
|
00001 /* 00002 * ***** BEGIN GPL LICENSE BLOCK ***** 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 Foundation, 00016 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00017 * 00018 * Contributor(s): Peter Schlaile <peter@schlaile.de> 2005 00019 * 00020 * ***** END GPL LICENSE BLOCK ***** 00021 */ 00022 00028 #ifndef MEM_CACHELIMITER_H 00029 #define MEM_CACHELIMITER_H 00030 00060 #include <list> 00061 #include "MEM_Allocator.h" 00062 00063 template<class T> 00064 class MEM_CacheLimiter; 00065 00066 #ifndef __MEM_cache_limiter_c_api_h_included__ 00067 extern "C" { 00068 extern void MEM_CacheLimiter_set_maximum(intptr_t m); 00069 extern intptr_t MEM_CacheLimiter_get_maximum(); 00070 }; 00071 #endif 00072 00073 template<class T> 00074 class MEM_CacheLimiterHandle { 00075 public: 00076 explicit MEM_CacheLimiterHandle(T * data_, 00077 MEM_CacheLimiter<T> * parent_) 00078 : data(data_), refcount(0), parent(parent_) { } 00079 00080 void ref() { 00081 refcount++; 00082 } 00083 void unref() { 00084 refcount--; 00085 } 00086 T * get() { 00087 return data; 00088 } 00089 const T * get() const { 00090 return data; 00091 } 00092 int get_refcount() const { 00093 return refcount; 00094 } 00095 bool can_destroy() const { 00096 return !data || !refcount; 00097 } 00098 bool destroy_if_possible() { 00099 if (can_destroy()) { 00100 delete data; 00101 data = 0; 00102 unmanage(); 00103 return true; 00104 } 00105 return false; 00106 } 00107 void unmanage() { 00108 parent->unmanage(this); 00109 } 00110 void touch() { 00111 parent->touch(this); 00112 } 00113 private: 00114 friend class MEM_CacheLimiter<T>; 00115 00116 T * data; 00117 int refcount; 00118 typename std::list<MEM_CacheLimiterHandle<T> *, 00119 MEM_Allocator<MEM_CacheLimiterHandle<T> *> >::iterator me; 00120 MEM_CacheLimiter<T> * parent; 00121 }; 00122 00123 template<class T> 00124 class MEM_CacheLimiter { 00125 public: 00126 typedef typename std::list<MEM_CacheLimiterHandle<T> *, 00127 MEM_Allocator<MEM_CacheLimiterHandle<T> *> >::iterator iterator; 00128 typedef intptr_t (*MEM_CacheLimiter_DataSize_Func) (void *data); 00129 MEM_CacheLimiter(MEM_CacheLimiter_DataSize_Func getDataSize_) 00130 : getDataSize(getDataSize_) { 00131 } 00132 ~MEM_CacheLimiter() { 00133 for (iterator it = queue.begin(); it != queue.end(); it++) { 00134 delete *it; 00135 } 00136 } 00137 MEM_CacheLimiterHandle<T> * insert(T * elem) { 00138 queue.push_back(new MEM_CacheLimiterHandle<T>(elem, this)); 00139 iterator it = queue.end(); 00140 --it; 00141 queue.back()->me = it; 00142 return queue.back(); 00143 } 00144 void unmanage(MEM_CacheLimiterHandle<T> * handle) { 00145 queue.erase(handle->me); 00146 delete handle; 00147 } 00148 void enforce_limits() { 00149 intptr_t max = MEM_CacheLimiter_get_maximum(); 00150 intptr_t mem_in_use, cur_size; 00151 00152 if (max == 0) { 00153 return; 00154 } 00155 00156 if(getDataSize) { 00157 mem_in_use = total_size(); 00158 } else { 00159 mem_in_use = MEM_get_memory_in_use(); 00160 } 00161 00162 for (iterator it = queue.begin(); 00163 it != queue.end() && mem_in_use > max;) 00164 { 00165 iterator jt = it; 00166 ++it; 00167 00168 if(getDataSize) { 00169 cur_size= getDataSize((*jt)->get()->get_data()); 00170 } else { 00171 cur_size= mem_in_use; 00172 } 00173 00174 (*jt)->destroy_if_possible(); 00175 00176 if(getDataSize) { 00177 mem_in_use-= cur_size; 00178 } else { 00179 mem_in_use-= cur_size - MEM_get_memory_in_use(); 00180 } 00181 } 00182 } 00183 void touch(MEM_CacheLimiterHandle<T> * handle) { 00184 queue.push_back(handle); 00185 queue.erase(handle->me); 00186 iterator it = queue.end(); 00187 --it; 00188 handle->me = it; 00189 } 00190 private: 00191 intptr_t total_size() { 00192 intptr_t size = 0; 00193 for (iterator it = queue.begin(); it != queue.end(); it++) { 00194 size+= getDataSize((*it)->get()->get_data()); 00195 } 00196 return size; 00197 } 00198 00199 std::list<MEM_CacheLimiterHandle<T>*, 00200 MEM_Allocator<MEM_CacheLimiterHandle<T> *> > queue; 00201 MEM_CacheLimiter_DataSize_Func getDataSize; 00202 }; 00203 00204 #endif // MEM_CACHELIMITER_H