Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Schlaile <peter@schlaile.de>2006-02-05 21:56:30 +0300
committerPeter Schlaile <peter@schlaile.de>2006-02-05 21:56:30 +0300
commit57d7ae0365b44752b8c38c3046d8f1b76c72362b (patch)
treed532b6b807402e4fe2ab2931b82e8b6118e1e272 /intern/memutil
parentd7e5f37172590f73501dc401aa6c66043259e741 (diff)
Adds generic memcache limitor (used by the new sequencer to cache
only a certain amount of frames).
Diffstat (limited to 'intern/memutil')
-rw-r--r--intern/memutil/MEM_Allocator.h89
-rw-r--r--intern/memutil/MEM_CacheLimiter.h170
-rw-r--r--intern/memutil/MEM_CacheLimiterC-Api.h141
-rw-r--r--intern/memutil/SConscript2
-rw-r--r--intern/memutil/intern/MEM_CacheLimiterC-Api.cpp195
-rw-r--r--intern/memutil/intern/Makefile2
6 files changed, 597 insertions, 2 deletions
diff --git a/intern/memutil/MEM_Allocator.h b/intern/memutil/MEM_Allocator.h
new file mode 100644
index 00000000000..40716496d16
--- /dev/null
+++ b/intern/memutil/MEM_Allocator.h
@@ -0,0 +1,89 @@
+/**
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Contributor(s): Peter Schlaile <peter@schlaile.de> 2005
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+#ifndef __MEM_Allocator_h_included__
+#define __MEM_Allocator_h_included__ 1
+
+#include "guardedalloc/MEM_guardedalloc.h"
+
+template<typename _Tp>
+struct MEM_Allocator
+{
+ typedef size_t size_type;
+ typedef ptrdiff_t difference_type;
+ typedef _Tp* pointer;
+ typedef const _Tp* const_pointer;
+ typedef _Tp& reference;
+ typedef const _Tp& const_reference;
+ typedef _Tp value_type;
+
+ template<typename _Tp1>
+ struct rebind {
+ typedef MEM_Allocator<_Tp1> other;
+ };
+
+ MEM_Allocator() throw() {}
+ MEM_Allocator(const MEM_Allocator& __a) throw() {}
+
+ template<typename _Tp1>
+ MEM_Allocator(const MEM_Allocator<_Tp1> __a) throw() { }
+
+ ~MEM_Allocator() throw() {}
+
+ pointer address(reference __x) const { return &__x; }
+
+ const_pointer address(const_reference __x) const { return &__x; }
+
+ // NB: __n is permitted to be 0. The C++ standard says nothing
+ // about what the return value is when __n == 0.
+ _Tp* allocate(size_type __n, const void* = 0) {
+ _Tp* __ret = 0;
+ if (__n)
+ __ret = static_cast<_Tp*>(
+ MEM_mallocN(__n * sizeof(_Tp),
+ "STL MEM_Allocator"));
+ return __ret;
+ }
+
+ // __p is not permitted to be a null pointer.
+ void deallocate(pointer __p, size_type){
+ MEM_freeN(__p);
+ }
+
+ size_type max_size() const throw() {
+ return size_t(-1) / sizeof(_Tp);
+ }
+
+ void construct(pointer __p, const _Tp& __val) {
+ new(__p) _Tp(__val);
+ }
+
+ void destroy(pointer __p) {
+ __p->~_Tp();
+ }
+};
+
+#endif
diff --git a/intern/memutil/MEM_CacheLimiter.h b/intern/memutil/MEM_CacheLimiter.h
new file mode 100644
index 00000000000..3026e827c3f
--- /dev/null
+++ b/intern/memutil/MEM_CacheLimiter.h
@@ -0,0 +1,170 @@
+/**
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Contributor(s): Peter Schlaile <peter@schlaile.de> 2005
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+#ifndef __MEM_cache_limiter_h_included__
+#define __MEM_cache_limiter_h_included__ 1
+
+/**
+ * @section MEM_CacheLimiter
+ * This class defines a generic memory cache management system
+ * to limit memory usage to a fixed global maximum.
+ *
+ * Please use the C-API in MEM_CacheLimiterC-Api.h for code written in C.
+ *
+ * Usage example:
+ *
+ * class BigFatImage {
+ * public:
+ * ~BigFatImage() { tell_everyone_we_are_gone(this); }
+ * };
+ *
+ * void doit() {
+ * MEM_Cache<BigFatImage> BigFatImages;
+ *
+ * MEM_Cache_Handle<BigFatImage>* h = BigFatImages.insert(new BigFatImage);
+ *
+ * BigFatImages.enforce_limits();
+ * h->ref();
+ *
+ * work with image...
+ *
+ * h->unref();
+ *
+ * leave image in cache.
+ */
+
+#include <list>
+#include "MEM_Allocator.h"
+
+template<class T>
+class MEM_CacheLimiter;
+
+#ifndef __MEM_cache_limiter_c_api_h_included__
+extern "C" {
+ extern void MEM_CacheLimiter_set_maximum(int m);
+ extern int MEM_CacheLimiter_get_maximum();
+};
+#endif
+
+template<class T>
+class MEM_CacheLimiterHandle {
+public:
+ explicit MEM_CacheLimiterHandle(T * data_,
+ MEM_CacheLimiter<T> * parent_)
+ : data(data_), refcount(0), parent(parent_) { }
+
+ void ref() {
+ refcount++;
+ }
+ void unref() {
+ refcount--;
+ }
+ T * get() {
+ return data;
+ }
+ const T * get() const {
+ return data;
+ }
+ int get_refcount() const {
+ return refcount;
+ }
+ bool can_destroy() const {
+ return !data || !refcount;
+ }
+ bool destroy_if_possible() {
+ if (can_destroy()) {
+ delete data;
+ data = 0;
+ unmanage();
+ return true;
+ }
+ return false;
+ }
+ void unmanage() {
+ parent->unmanage(this);
+ }
+ void touch() {
+ parent->touch(this);
+ }
+private:
+ friend class MEM_CacheLimiter<T>;
+
+ T * data;
+ int refcount;
+ typename std::list<MEM_CacheLimiterHandle<T> *,
+ MEM_Allocator<MEM_CacheLimiterHandle<T> *> >::iterator me;
+ MEM_CacheLimiter<T> * parent;
+};
+
+template<class T>
+class MEM_CacheLimiter {
+public:
+ typedef typename std::list<MEM_CacheLimiterHandle<T> *,
+ MEM_Allocator<MEM_CacheLimiterHandle<T> *> >::iterator iterator;
+ ~MEM_CacheLimiter() {
+ for (iterator it = queue.begin(); it != queue.end(); it++) {
+ delete *it;
+ }
+ }
+ MEM_CacheLimiterHandle<T> * insert(T * elem) {
+ queue.push_back(new MEM_CacheLimiterHandle<T>(elem, this));
+ iterator it = queue.end();
+ --it;
+ queue.back()->me = it;
+ return queue.back();
+ }
+ void unmanage(MEM_CacheLimiterHandle<T> * handle) {
+ queue.erase(handle->me);
+ delete handle;
+ }
+ void enforce_limits() {
+ // this is rather _ugly_!
+ extern int mem_in_use;
+
+ int max = MEM_CacheLimiter_get_maximum();
+ if (max == 0) {
+ return;
+ }
+ for (iterator it = queue.begin();
+ it != queue.end() && mem_in_use > max;) {
+ iterator jt = it;
+ ++it;
+ (*jt)->destroy_if_possible();
+ }
+ }
+ void touch(MEM_CacheLimiterHandle<T> * handle) {
+ queue.push_back(handle);
+ queue.erase(handle->me);
+ iterator it = queue.end();
+ --it;
+ handle->me = it;
+ }
+private:
+ std::list<MEM_CacheLimiterHandle<T>*,
+ MEM_Allocator<MEM_CacheLimiterHandle<T> *> > queue;
+};
+
+#endif
diff --git a/intern/memutil/MEM_CacheLimiterC-Api.h b/intern/memutil/MEM_CacheLimiterC-Api.h
new file mode 100644
index 00000000000..c21b91491e8
--- /dev/null
+++ b/intern/memutil/MEM_CacheLimiterC-Api.h
@@ -0,0 +1,141 @@
+/**
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Contributor(s): Peter Schlaile <peter@schlaile.de> 2005
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+#ifndef __MEM_cache_limiter_c_api_h_included__
+#define __MEM_cache_limiter_c_api_h_included__ 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct MEM_CacheLimiter_s;
+struct MEM_CacheLimiterHandle_s;
+
+typedef struct MEM_CacheLimiter_s MEM_CacheLimiterC;
+typedef struct MEM_CacheLimiterHandle_s MEM_CacheLimiterHandleC;
+
+#ifndef __MEM_cache_limiter_h_included__
+extern void MEM_CacheLimiter_set_maximum(int m);
+extern int MEM_CacheLimiter_get_maximum();
+#endif
+/**
+ * Create new MEM_CacheLimiter object
+ * managed objects are destructed with the data_destructor
+ *
+ * @param data_destructor
+ * @return A new MEM_CacheLimter object
+ */
+
+extern MEM_CacheLimiterC * new_MEM_CacheLimiter(
+ void (*data_destructor) (void * data));
+
+/**
+ * Delete MEM_CacheLimiter
+ *
+ * Frees the memory of the CacheLimiter but does not touch managed objects!
+ *
+ * @param This "This" pointer
+ */
+
+extern void delete_MEM_CacheLimiter(MEM_CacheLimiterC * This);
+
+/**
+ * Manage object
+ *
+ * @param This "This" pointer, data data object to manage
+ * @return CacheLimiterHandle to ref, unref, touch the managed object
+ */
+
+extern MEM_CacheLimiterHandleC * MEM_CacheLimiter_insert(
+ MEM_CacheLimiterC * This, void * data);
+
+/**
+ * Free objects until memory constraints are satisfied
+ *
+ * @param This "This" pointer
+ */
+
+extern void MEM_CacheLimiter_enforce_limits(MEM_CacheLimiterC * This);
+
+/**
+ * Unmanage object previously inserted object.
+ * Does _not_ delete managed object!
+ *
+ * @param This "This" pointer, handle of object
+ */
+
+extern void MEM_CacheLimiter_unmanage(MEM_CacheLimiterHandleC * handle);
+
+
+/**
+ * Raise priority of object (put it at the tail of the deletion chain)
+ *
+ * @param handle of object
+ */
+
+extern void MEM_CacheLimiter_touch(MEM_CacheLimiterHandleC * handle);
+
+/**
+ * Increment reference counter. Objects with reference counter != 0 are _not_
+ * deleted.
+ *
+ * @param handle of object
+ */
+
+extern void MEM_CacheLimiter_ref(MEM_CacheLimiterHandleC * handle);
+
+/**
+ * Decrement reference counter. Objects with reference counter != 0 are _not_
+ * deleted.
+ *
+ * @param handle of object
+ */
+
+extern void MEM_CacheLimiter_unref(MEM_CacheLimiterHandleC * handle);
+
+/**
+ * Get reference counter.
+ *
+ * @param This "This" pointer, handle of object
+ */
+
+extern int MEM_CacheLimiter_get_refcount(MEM_CacheLimiterHandleC * handle);
+
+/**
+ * Get pointer to managed object
+ *
+ * @param handle of object
+ */
+
+extern void * MEM_CacheLimiter_get(MEM_CacheLimiterHandleC * handle);
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif
+
diff --git a/intern/memutil/SConscript b/intern/memutil/SConscript
index 4d17f13f214..dace305e91d 100644
--- a/intern/memutil/SConscript
+++ b/intern/memutil/SConscript
@@ -3,6 +3,6 @@ Import ('env')
sources = env.Glob('intern/*.cpp')
-incs = '.'
+incs = '. ..'
env.BlenderLib ('blender_MEM', sources, Split(incs), [], libtype='intern', priority = 10 )
diff --git a/intern/memutil/intern/MEM_CacheLimiterC-Api.cpp b/intern/memutil/intern/MEM_CacheLimiterC-Api.cpp
new file mode 100644
index 00000000000..a259569740b
--- /dev/null
+++ b/intern/memutil/intern/MEM_CacheLimiterC-Api.cpp
@@ -0,0 +1,195 @@
+/**
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Contributor(s): Peter Schlaile <peter@schlaile.de> 2005
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "MEM_CacheLimiter.h"
+#include "MEM_CacheLimiterC-Api.h"
+
+static int & get_max()
+{
+ static int m = 32*1024*1024;
+ return m;
+}
+
+void MEM_CacheLimiter_set_maximum(int m)
+{
+ get_max() = m;
+}
+
+int MEM_CacheLimiter_get_maximum()
+{
+ return get_max();
+}
+
+class MEM_CacheLimiterHandleCClass;
+class MEM_CacheLimiterCClass;
+
+typedef MEM_CacheLimiterHandle<MEM_CacheLimiterHandleCClass> handle_t;
+typedef MEM_CacheLimiter<MEM_CacheLimiterHandleCClass> cache_t;
+typedef std::list<MEM_CacheLimiterHandleCClass*,
+ MEM_Allocator<MEM_CacheLimiterHandleCClass* > > list_t;
+
+class MEM_CacheLimiterCClass {
+public:
+ MEM_CacheLimiterCClass(void (*data_destructor_) (void * data))
+ : data_destructor(data_destructor_) {
+ }
+ ~MEM_CacheLimiterCClass();
+
+ handle_t * insert(void * data);
+
+ void destruct(void * data,
+ list_t::iterator it);
+
+ cache_t * get_cache() {
+ return &cache;
+ }
+private:
+ void (*data_destructor) (void * data);
+
+ MEM_CacheLimiter<MEM_CacheLimiterHandleCClass> cache;
+
+ list_t cclass_list;
+};
+
+class MEM_CacheLimiterHandleCClass {
+public:
+ MEM_CacheLimiterHandleCClass(void * data_,
+ MEM_CacheLimiterCClass * parent_)
+ : data(data_), parent(parent_) { }
+ ~MEM_CacheLimiterHandleCClass();
+ void set_iter(list_t::iterator it_) {
+ it = it_;
+ }
+ void set_data(void * data_) {
+ data = data_;
+ }
+ void * get_data() const {
+ return data;
+ }
+private:
+ void * data;
+ MEM_CacheLimiterCClass * parent;
+ list_t::iterator it;
+};
+
+handle_t * MEM_CacheLimiterCClass::insert(void * data)
+{
+ cclass_list.push_back(new MEM_CacheLimiterHandleCClass(data, this));
+ list_t::iterator it = cclass_list.end();
+ --it;
+ cclass_list.back()->set_iter(it);
+
+ return cache.insert(cclass_list.back());
+}
+
+void MEM_CacheLimiterCClass::destruct(void * data, list_t::iterator it)
+{
+ data_destructor(data);
+ cclass_list.erase(it);
+}
+
+MEM_CacheLimiterHandleCClass::~MEM_CacheLimiterHandleCClass()
+{
+ if (data) {
+ parent->destruct(data, it);
+ }
+}
+
+MEM_CacheLimiterCClass::~MEM_CacheLimiterCClass()
+{
+ // should not happen, but don't leak memory in this case...
+ for (list_t::iterator it = cclass_list.begin();
+ it != cclass_list.end(); it++) {
+ (*it)->set_data(0);
+ delete *it;
+ }
+}
+
+// ----------------------------------------------------------------------
+
+static inline MEM_CacheLimiterCClass* cast(MEM_CacheLimiterC * l)
+{
+ return (MEM_CacheLimiterCClass*) l;
+}
+
+static inline handle_t* cast(MEM_CacheLimiterHandleC * l)
+{
+ return (handle_t*) l;
+}
+
+MEM_CacheLimiterC * new_MEM_CacheLimiter(
+ void (*data_destructor) (void * data))
+{
+ return (MEM_CacheLimiterC*) new MEM_CacheLimiterCClass(
+ data_destructor);
+}
+
+void delete_MEM_CacheLimiter(MEM_CacheLimiterC * This)
+{
+ delete cast(This);
+}
+
+MEM_CacheLimiterHandleC * MEM_CacheLimiter_insert(
+ MEM_CacheLimiterC * This, void * data)
+{
+ return (MEM_CacheLimiterHandleC *) cast(This)->insert(data);
+}
+
+void MEM_CacheLimiter_enforce_limits(MEM_CacheLimiterC * This)
+{
+ cast(This)->get_cache()->enforce_limits();
+}
+
+void MEM_CacheLimiter_unmanage(MEM_CacheLimiterHandleC * handle)
+{
+ cast(handle)->unmanage();
+}
+
+void MEM_CacheLimiter_touch(MEM_CacheLimiterHandleC * handle)
+{
+ cast(handle)->touch();
+}
+
+void MEM_CacheLimiter_ref(MEM_CacheLimiterHandleC * handle)
+{
+ cast(handle)->ref();
+}
+
+void MEM_CacheLimiter_unref(MEM_CacheLimiterHandleC * handle)
+{
+ cast(handle)->unref();
+}
+
+int MEM_CacheLimiter_get_refcount(MEM_CacheLimiterHandleC * handle)
+{
+ return cast(handle)->get_refcount();
+}
+
+
+void * MEM_CacheLimiter_get(MEM_CacheLimiterHandleC * handle)
+{
+ return cast(handle)->get()->get_data();
+}
diff --git a/intern/memutil/intern/Makefile b/intern/memutil/intern/Makefile
index 0d0d3af6327..71ffa6fa7e4 100644
--- a/intern/memutil/intern/Makefile
+++ b/intern/memutil/intern/Makefile
@@ -38,5 +38,5 @@ include nan_compile.mk
CCFLAGS += $(LEVEL_2_CPP_WARNINGS)
-CPPFLAGS += -I..
+CPPFLAGS += -I.. -I../..