diff options
-rw-r--r-- | source/blender/blenkernel/intern/library.c | 10 | ||||
-rw-r--r-- | source/blender/python/BPY_extern.h | 2 | ||||
-rw-r--r-- | source/blender/python/intern/bpy_rna.c | 49 | ||||
-rw-r--r-- | source/blender/python/intern/bpy_rna.h | 3 |
4 files changed, 57 insertions, 7 deletions
diff --git a/source/blender/blenkernel/intern/library.c b/source/blender/blenkernel/intern/library.c index bb6d3c490d0..b2e0bb20f55 100644 --- a/source/blender/blenkernel/intern/library.c +++ b/source/blender/blenkernel/intern/library.c @@ -109,6 +109,10 @@ #include "BKE_gpencil.h" #include "BKE_fcurve.h" +#ifdef WITH_PYTHON +#include "BPY_extern.h" +#endif + #define MAX_IDPUP 60 /* was 24 */ /* GS reads the memory pointed at in a specific ordering. @@ -721,7 +725,11 @@ static void animdata_dtar_clear_cb(ID *UNUSED(id), AnimData *adt, void *userdata void free_libblock(ListBase *lb, void *idv) { ID *id= idv; - + +#ifdef WITH_PYTHON + BPY_id_release(id); +#endif + switch( GS(id->name) ) { /* GetShort from util.h */ case ID_SCE: free_scene((Scene *)id); diff --git a/source/blender/python/BPY_extern.h b/source/blender/python/BPY_extern.h index f4899849702..7901957e5e4 100644 --- a/source/blender/python/BPY_extern.h +++ b/source/blender/python/BPY_extern.h @@ -93,6 +93,8 @@ void BPY_DECREF(void *pyob_ptr); /* Py_DECREF() */ int BPY_context_member_get(struct bContext *C, const char *member, struct bContextDataResult *result); void BPY_context_set(struct bContext *C); +void BPY_id_release(struct ID *id); + #ifdef __cplusplus } /* extern "C" */ #endif diff --git a/source/blender/python/intern/bpy_rna.c b/source/blender/python/intern/bpy_rna.c index 561cc289e62..bc216207821 100644 --- a/source/blender/python/intern/bpy_rna.c +++ b/source/blender/python/intern/bpy_rna.c @@ -94,17 +94,54 @@ static int pyrna_prop_validity_check(BPy_PropertyRNA *self) return -1; } -/* -static void pyrna_struct_invalidate(BPy_StructRNA *self) +static void pyrna_invalidate(BPy_DummyPointerRNA *self) { - self->ptr.type= NULL; + self->ptr.type= NULL; /* this is checked for validity */ + self->ptr.id.data= NULL; /* should not be needed but prevent bad pointer access, just incase */ +} + +#ifdef USE_PYRNA_INVALIDATE_GC +#define FROM_GC(g) ((PyObject *)(((PyGC_Head *)g)+1)) + +/* only for sizeof() */ +struct gc_generation { + PyGC_Head head; + int threshold; + int count; +} gc_generation; + +static void id_release_gc(struct ID *id) +{ + unsigned int j; + // unsigned int i= 0; + for(j=0; j<3; j++) { + /* hack below to get the 2 other lists from _PyGC_generation0 that are normally not exposed */ + PyGC_Head *gen= (PyGC_Head *)(((char *)_PyGC_generation0) + (sizeof(gc_generation) * j)); + PyGC_Head *g = gen->gc.gc_next; + while ((g= g->gc.gc_next) != gen) { + PyObject *ob= FROM_GC(g); + if(PyType_IsSubtype(Py_TYPE(ob), &pyrna_struct_Type) || PyType_IsSubtype(Py_TYPE(ob), &pyrna_prop_Type)) { + BPy_DummyPointerRNA *ob_ptr= (BPy_DummyPointerRNA *)ob; + if(ob_ptr->ptr.id.data == id) { + pyrna_invalidate(ob_ptr); + // printf("freeing: %p %s, %.200s\n", (void *)ob, id->name, Py_TYPE(ob)->tp_name); + // i++; + } + } + } + } + // printf("id_release_gc freed '%s': %d\n", id->name, i); } +#endif + -static void pyrna_prop_invalidate(BPy_PropertyRNA *self) +void BPY_id_release(struct ID *id) { - self->ptr.type= NULL; + (void)id; +#ifdef USE_PYRNA_INVALIDATE_GC + id_release_gc(id); +#endif } -*/ #ifdef USE_PEDANTIC_WRITE static short rna_disallow_writes= FALSE; diff --git a/source/blender/python/intern/bpy_rna.h b/source/blender/python/intern/bpy_rna.h index fe30529f680..8d9fabf5627 100644 --- a/source/blender/python/intern/bpy_rna.h +++ b/source/blender/python/intern/bpy_rna.h @@ -44,6 +44,9 @@ extern PyTypeObject pyrna_prop_collection_Type; #define BPy_PropertyRNA_Check(v) (PyObject_TypeCheck(v, &pyrna_prop_Type)) #define BPy_PropertyRNA_CheckExact(v) (Py_TYPE(v) == &pyrna_prop_Type) +/* method to invalidate removed py data, XXX, slow to remove objects, otherwise no overhead */ +// #define USE_PYRNA_INVALIDATE_GC + /* play it safe and keep optional for now, need to test further now this affects looping on 10000's of verts for eg. */ // #define USE_WEAKREFS |