|
Blender
V2.59
|
00001 /* 00002 * 00003 * ***** BEGIN GPL LICENSE BLOCK ***** 00004 * 00005 * This program is free software; you can redistribute it and/or 00006 * modify it under the terms of the GNU General Public License 00007 * as published by the Free Software Foundation; either version 2 00008 * of the License, or (at your option) any later version. 00009 * 00010 * This program is distributed in the hope that it will be useful, 00011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00013 * GNU General Public License for more details. 00014 * 00015 * You should have received a copy of the GNU General Public License 00016 * along with this program; if not, write to the Free Software Foundation, 00017 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00018 * 00019 * Contributor(s): Peter Schlaile <peter@schlaile.de> 2005 00020 * 00021 * ***** END GPL LICENSE BLOCK ***** 00022 */ 00023 00029 #ifndef MEM_CACHELIMITER_H 00030 #define MEM_CACHELIMITER_H 00031 00061 #include <list> 00062 #include "MEM_Allocator.h" 00063 00064 template<class T> 00065 class MEM_CacheLimiter; 00066 00067 #ifndef __MEM_cache_limiter_c_api_h_included__ 00068 extern "C" { 00069 extern void MEM_CacheLimiter_set_maximum(intptr_t m); 00070 extern intptr_t MEM_CacheLimiter_get_maximum(); 00071 }; 00072 #endif 00073 00074 template<class T> 00075 class MEM_CacheLimiterHandle { 00076 public: 00077 explicit MEM_CacheLimiterHandle(T * data_, 00078 MEM_CacheLimiter<T> * parent_) 00079 : data(data_), refcount(0), parent(parent_) { } 00080 00081 void ref() { 00082 refcount++; 00083 } 00084 void unref() { 00085 refcount--; 00086 } 00087 T * get() { 00088 return data; 00089 } 00090 const T * get() const { 00091 return data; 00092 } 00093 int get_refcount() const { 00094 return refcount; 00095 } 00096 bool can_destroy() const { 00097 return !data || !refcount; 00098 } 00099 bool destroy_if_possible() { 00100 if (can_destroy()) { 00101 delete data; 00102 data = 0; 00103 unmanage(); 00104 return true; 00105 } 00106 return false; 00107 } 00108 void unmanage() { 00109 parent->unmanage(this); 00110 } 00111 void touch() { 00112 parent->touch(this); 00113 } 00114 private: 00115 friend class MEM_CacheLimiter<T>; 00116 00117 T * data; 00118 int refcount; 00119 typename std::list<MEM_CacheLimiterHandle<T> *, 00120 MEM_Allocator<MEM_CacheLimiterHandle<T> *> >::iterator me; 00121 MEM_CacheLimiter<T> * parent; 00122 }; 00123 00124 template<class T> 00125 class MEM_CacheLimiter { 00126 public: 00127 typedef typename std::list<MEM_CacheLimiterHandle<T> *, 00128 MEM_Allocator<MEM_CacheLimiterHandle<T> *> >::iterator iterator; 00129 ~MEM_CacheLimiter() { 00130 for (iterator it = queue.begin(); it != queue.end(); it++) { 00131 delete *it; 00132 } 00133 } 00134 MEM_CacheLimiterHandle<T> * insert(T * elem) { 00135 queue.push_back(new MEM_CacheLimiterHandle<T>(elem, this)); 00136 iterator it = queue.end(); 00137 --it; 00138 queue.back()->me = it; 00139 return queue.back(); 00140 } 00141 void unmanage(MEM_CacheLimiterHandle<T> * handle) { 00142 queue.erase(handle->me); 00143 delete handle; 00144 } 00145 void enforce_limits() { 00146 intptr_t max = MEM_CacheLimiter_get_maximum(); 00147 intptr_t mem_in_use= MEM_get_memory_in_use(); 00148 intptr_t mmap_in_use= MEM_get_mapped_memory_in_use(); 00149 00150 if (max == 0) { 00151 return; 00152 } 00153 for (iterator it = queue.begin(); 00154 it != queue.end() && mem_in_use + mmap_in_use > max;) { 00155 iterator jt = it; 00156 ++it; 00157 (*jt)->destroy_if_possible(); 00158 } 00159 } 00160 void touch(MEM_CacheLimiterHandle<T> * handle) { 00161 queue.push_back(handle); 00162 queue.erase(handle->me); 00163 iterator it = queue.end(); 00164 --it; 00165 handle->me = it; 00166 } 00167 private: 00168 std::list<MEM_CacheLimiterHandle<T>*, 00169 MEM_Allocator<MEM_CacheLimiterHandle<T> *> > queue; 00170 }; 00171 00172 #endif // MEM_CACHELIMITER_H