[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [11156] branches/pyapi_devel/source/ blender/python/api2_2x: Saddly thin wrapping blenders linkedLists is not safe - its possible blender can remove the an item while looping .

Campbell Barton cbarton at metavr.com
Tue Jul 3 16:09:22 CEST 2007


Revision: 11156
          http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=11156
Author:   campbellbarton
Date:     2007-07-03 16:09:22 +0200 (Tue, 03 Jul 2007)

Log Message:
-----------
Saddly thin wrapping blenders linkedLists is not safe - its possible blender can remove the an item while looping.

made group and scene objects iters store indicies rather then Base or GroupObject for storing the iter location.
MetaElements do the same thing.

This is slower because every time the next item advances it needs to travel up the linked list from the first item to the new index.
So its a thin wrapper still but not as fast.

Modified Paths:
--------------
    branches/pyapi_devel/source/blender/python/api2_2x/Group.c
    branches/pyapi_devel/source/blender/python/api2_2x/Group.h
    branches/pyapi_devel/source/blender/python/api2_2x/Metaball.c
    branches/pyapi_devel/source/blender/python/api2_2x/Metaball.h
    branches/pyapi_devel/source/blender/python/api2_2x/Scene.c
    branches/pyapi_devel/source/blender/python/api2_2x/Scene.h

Modified: branches/pyapi_devel/source/blender/python/api2_2x/Group.c
===================================================================
--- branches/pyapi_devel/source/blender/python/api2_2x/Group.c	2007-07-03 11:53:17 UTC (rev 11155)
+++ branches/pyapi_devel/source/blender/python/api2_2x/Group.c	2007-07-03 14:09:22 UTC (rev 11156)
@@ -164,7 +164,7 @@
 /*****************************************************************************/
 
 /* internal */
-static PyObject *GroupObSeq_CreatePyObject( BPy_Group *self, GroupObject *iter );
+static PyObject *Group_getObjects( BPy_Group *self );
 
 /*****************************************************************************/
 /* Python BPy_Group methods table:					   */
@@ -217,12 +217,7 @@
  * Python BPy_Object attributes
  *
  ************************************************************************/
-static PyObject *Group_getObjects( BPy_Group * self )
-{
-	return GroupObSeq_CreatePyObject(self, NULL);
-}
 
-
 static void add_to_group_wraper(Group *group, Object *ob) {
 	Base *base;
 	add_to_group(group, ob);
@@ -236,6 +231,15 @@
 	}
 }
 
+/* could also be called GroupObSeq_CreatePyObject*/
+static PyObject *Group_getObjects( BPy_Group *self )
+{
+	BPy_GroupObSeq *seq = PyObject_NEW( BPy_GroupObSeq, &GroupObSeq_Type);
+	seq->bpygroup = self; Py_INCREF(self);
+	seq->index= 0;
+	return (PyObject *)seq;
+}
+
 /* only for internal use Blender.Group.Get("MyGroup").objects= []*/
 static int Group_setObjects( BPy_Group * self, PyObject * args )
 {
@@ -516,55 +520,31 @@
  * create a thin GroupOb object
  */
 
-static PyObject *GroupObSeq_CreatePyObject( BPy_Group *self, GroupObject *iter )
+/* internal use only */
+static  GroupObject *GroupObSeq_get_pointer( BPy_GroupObSeq* self )
 {
-	BPy_GroupObSeq *seq = PyObject_NEW( BPy_GroupObSeq, &GroupObSeq_Type);
-	seq->bpygroup = self; Py_INCREF(self);
-	seq->iter= iter;
-	return (PyObject *)seq;
+	GroupObject *group_ob;
+	int i;
+	
+	if (!self->bpygroup->group)
+		return NULL;
+	
+	group_ob = self->bpygroup->group->gobject.first;
+	for (i=0; (group_ob && i<self->index); i++, group_ob= group_ob->next) {}
+	return group_ob; /* can be NULL */
 }
 
-
 static int GroupObSeq_len( BPy_GroupObSeq * self )
 {
 	GROUP_DEL_CHECK_INT(self->bpygroup);
 	return BLI_countlist( &( self->bpygroup->group->gobject ) );
 }
 
-/*
- * retrive a single GroupOb from somewhere in the GroupObex list
- */
-
-static PyObject *GroupObSeq_item( BPy_GroupObSeq * self, int i )
-{
-	Group *group= self->bpygroup->group;
-	int index=0;
-	PyObject *bpy_obj;
-	GroupObject *gob;
-	
-	GROUP_DEL_CHECK_PY(self->bpygroup);
-	
-	for (gob= group->gobject.first; gob && i!=index; gob= gob->next, index++) {}
-	
-	if (!(gob))
-		return EXPP_ReturnPyObjError( PyExc_IndexError,
-					      "array index out of range" );
-	
-	bpy_obj = Object_CreatePyObject( gob->ob );
-
-	if( !bpy_obj )
-		return EXPP_ReturnPyObjError( PyExc_RuntimeError,
-				"PyObject_New() failed" );
-
-	return (PyObject *)bpy_obj;
-	
-}
-
 static PySequenceMethods GroupObSeq_as_sequence = {
 	( inquiry ) GroupObSeq_len,	/* sq_length */
 	( binaryfunc ) 0,	/* sq_concat */
 	( intargfunc ) 0,	/* sq_repeat */
-	( intargfunc ) GroupObSeq_item,	/* sq_item */
+	( intargfunc ) 0,	/* sq_item */
 	( intintargfunc ) 0,	/* sq_slice */
 	( intobjargproc ) 0,	/* sq_ass_item */
 	( intintobjargproc ) 0,	/* sq_ass_slice */
@@ -585,11 +565,10 @@
 {
 	GROUP_DEL_CHECK_PY(self->bpygroup);
 	
-	if (!self->iter) {
-		self->iter = self->bpygroup->group->gobject.first;
+	if (self->index == 0) { /* were alredy looping */
 		return EXPP_incr_ret ( (PyObject *) self );
 	} else {
-		return GroupObSeq_CreatePyObject(self->bpygroup, self->bpygroup->group->gobject.first);
+		return Group_getObjects(self->bpygroup);
 	}
 }
 
@@ -599,27 +578,23 @@
 
 static PyObject *GroupObSeq_nextIter( BPy_GroupObSeq * self )
 {
-	PyObject *object;
-	if( !(self->iter) ||  !(self->bpygroup->group) ) {
-		self->iter = NULL; /* so we can add objects again */
+	GroupObject *group_ob = GroupObSeq_get_pointer(self);
+
+	if( !(group_ob) )
 		return EXPP_ReturnPyObjError( PyExc_StopIteration,
 				"iterator at end" );
-	}
-	
-	object= Object_CreatePyObject( self->iter->ob ); 
-	self->iter= self->iter->next;
-	return object;
+
+	self->index++; /* next, if this is un-initialized will go from -1 to 0 */
+
+	return  Object_CreatePyObject( group_ob->ob ); 
 }
 
 
-static PyObject *GroupObSeq_link( BPy_GroupObSeq * self, PyObject *args )
-{
-	PyObject *pyobj;
-	Object *blen_ob;
-	
+static PyObject *GroupObSeq_link( BPy_GroupObSeq * self, BPy_Object *value )
+{	
 	GROUP_DEL_CHECK_PY(self->bpygroup);
 	
-	if( !PyArg_ParseTuple( args, "O!", &Object_Type, &pyobj ) )
+	if( !BPy_Object_Check(value) )
 		return ( EXPP_ReturnPyObjError( PyExc_TypeError,
 				"expected a python object as an argument" ) );
 	
@@ -629,35 +604,27 @@
 					      "Cannot modify group objects while iterating" );
 	*/
 	
-	blen_ob = ( ( BPy_Object * ) pyobj )->object;
+	add_to_group_wraper(self->bpygroup->group, value->object); /* this checks so as not to add the object into the group twice*/
 	
-	add_to_group_wraper(self->bpygroup->group, blen_ob); /* this checks so as not to add the object into the group twice*/
-	
 	Py_RETURN_NONE;
 }
 
-static PyObject *GroupObSeq_unlink( BPy_GroupObSeq * self, PyObject *args )
-{
-	PyObject *pyobj;
-	Object *blen_ob;
-	Base *base= NULL;
-	
+static PyObject *GroupObSeq_unlink( BPy_GroupObSeq * self, BPy_Object *value )
+{	
 	GROUP_DEL_CHECK_PY(self->bpygroup);
 	
-	if( !PyArg_ParseTuple( args, "O!", &Object_Type, &pyobj ) )
+	if( !BPy_Object_Check(value) )
 		return ( EXPP_ReturnPyObjError( PyExc_TypeError,
 				"expected a python object as an argument" ) );
-	
-	blen_ob = ( ( BPy_Object * ) pyobj )->object;
-	
 
+	rem_from_group(self->bpygroup->group, value->object);
 	
-	rem_from_group(self->bpygroup->group, blen_ob);
-	
-	if(find_group(blen_ob)==NULL) {
-		blen_ob->flag &= ~OB_FROMGROUP;
+	if(find_group(value->object)==NULL) {
+		Base *base;
 		
-		base= object_in_scene(blen_ob, G.scene);
+		value->object->flag &= ~OB_FROMGROUP;
+		
+		base = object_in_scene(value->object, G.scene); 
 		if (base)
 			base->flag &= ~OB_FROMGROUP;
 	}
@@ -665,8 +632,8 @@
 }
 
 static struct PyMethodDef BPy_GroupObSeq_methods[] = {
-	{"link", (PyCFunction)GroupObSeq_link, METH_VARARGS, GroupObSeq_link_doc},
-	{"unlink", (PyCFunction)GroupObSeq_unlink, METH_VARARGS, GroupObSeq_unlink_doc},
+	{"link", (PyCFunction)GroupObSeq_link, METH_O, GroupObSeq_link_doc},
+	{"unlink", (PyCFunction)GroupObSeq_unlink, METH_O, GroupObSeq_unlink_doc},
 	{NULL, NULL, 0, NULL}	
 };
 

Modified: branches/pyapi_devel/source/blender/python/api2_2x/Group.h
===================================================================
--- branches/pyapi_devel/source/blender/python/api2_2x/Group.h	2007-07-03 11:53:17 UTC (rev 11155)
+++ branches/pyapi_devel/source/blender/python/api2_2x/Group.h	2007-07-03 14:09:22 UTC (rev 11156)
@@ -48,15 +48,15 @@
 /*****************************************************************************/
 typedef struct {
 	PyObject_HEAD
-	struct Group *group; 
+	struct Group *group;
 } BPy_Group;
 
 
 /* Group object sequence, iterate on the groups object listbase*/
 typedef struct {
-	PyObject_VAR_HEAD /* required python macro   */
-	BPy_Group *bpygroup; /* link to the python group so we can know if its been removed */
-	GroupObject *iter; /* so we can iterate over the objects */
+	PyObject_VAR_HEAD		/* required python macro   */
+	BPy_Group *bpygroup;	/* link to the python group so we can know if its been removed */
+	int index;				/* so we can iterate over the objects */
 } BPy_GroupObSeq;
 
 void Group_Init( void );

Modified: branches/pyapi_devel/source/blender/python/api2_2x/Metaball.c
===================================================================
--- branches/pyapi_devel/source/blender/python/api2_2x/Metaball.c	2007-07-03 11:53:17 UTC (rev 11155)
+++ branches/pyapi_devel/source/blender/python/api2_2x/Metaball.c	2007-07-03 14:09:22 UTC (rev 11156)
@@ -51,8 +51,8 @@
 #import "bpy_list.h"
 
 /* checks for the metaelement being removed */
-#define METAELEM_DEL_CHECK_PY(bpy_meta_elem) if (!(bpy_meta_elem->metaelem)) return ( EXPP_ReturnPyObjError( PyExc_RuntimeError, "Metaball has been removed" ) );
-#define METAELEM_DEL_CHECK_INT(bpy_meta_elem) if (!(bpy_meta_elem->metaelem)) return ( EXPP_ReturnIntError( PyExc_RuntimeError, "Metaball has been removed" ) );
+#define METAELEM_DEL_CHECK_PY(_ml) if (!_ml) return ( EXPP_ReturnPyObjError( PyExc_RuntimeError, "Metaball has been removed" ) );
+#define METAELEM_DEL_CHECK_INT(_ml) if (!_ml) return ( EXPP_ReturnIntError( PyExc_RuntimeError, "Metaball has been removed" ) );
 
 /*****************************************************************************/
 /* Python API function prototypes for the Metaball module.                   */
@@ -77,6 +77,21 @@
 	{NULL, NULL, 0, NULL}
 };
 
+/* internal use only */
+static MetaElem *MetaElem_get_pointer( MetaBall *mb, int index )
+{
+	MetaElem *ml;
+	int i;
+	
+	if (index==-1) /* removed */
+		return NULL;
+	
+	ml = mb->elems.first;
+	
+	for (i=0; (ml && i<index); i++, ml= ml->next) {}
+	return ml; /* can be NULL */
+}
+
 static PyObject *M_MetaElem_TypesDict( void )
 {
 	PyObject *Types = PyConstant_New(  );
@@ -562,11 +577,11 @@
 }
 
 
-static PyObject *MetaElemSeq_CreatePyObject(BPy_Metaball *self, MetaElem *iter)
+static PyObject *MetaElemSeq_CreatePyObject( BPy_Metaball *self )
 {
 	BPy_MetaElemSeq *seq = PyObject_NEW( BPy_MetaElemSeq, &MetaElemSeq_Type);
 	seq->bpymetaball = self; Py_INCREF(self);
-	seq->iter= iter;
+	seq->index= 0;
 	return (PyObject *)seq;
 }
 
@@ -575,7 +590,7 @@
  */
 static PyObject *Metaball_getElements( BPy_Metaball * self )
 {
-	return MetaElemSeq_CreatePyObject(self, NULL);
+	return MetaElemSeq_CreatePyObject(self);
 }
 
 /*
@@ -584,7 +599,7 @@
 /* This is a callback function for the BPy_Metaelem type. It is */
 static void Metaelem_dealloc( BPy_Metaelem * self )
 {
-	self->metaelem= NULL; /* so any references to the same bpyobject will raise an error */
+	Py_DECREF( self->bpymetaball );
 	PyObject_DEL( self );
 }
 
@@ -592,36 +607,29 @@
  * elem.type - int to set the shape of the element
  */
 static PyObject *Metaelem_getType( BPy_Metaelem *self )
-{
-	PyObject *attr = NULL;
+{	
 	
-	METAELEM_DEL_CHECK_PY(self);
-	
-	attr = PyInt_FromLong( self->metaelem->type );
-	
-	if( attr )
-		return attr;
-
-	return EXPP_ReturnPyObjError( PyExc_MemoryError,
-				"metaelem.type - PyInt_FromLong() failed!" );

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list