[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [58110] trunk/blender/source/blender: Fixed more threading issues with metaballs

Sergey Sharybin sergey.vfx at gmail.com
Tue Jul 9 10:23:01 CEST 2013


Revision: 58110
          http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-blender&revision=58110
Author:   nazgul
Date:     2013-07-09 08:23:01 +0000 (Tue, 09 Jul 2013)
Log Message:
-----------
Fixed more threading issues with metaballs

This time issue was caused by static variables used in
BKE_scene_base_iter_next function.

Change is not so much ultimate actually, but didn't
find more clear solution for now. So the changes are:

- Wrap almost all the static variables into own context-
  like structure, which is owned by the callee function
  and getting passed to the iteration function.

- Recursion detection wasn't possible with such approach,
  so recursion detection still uses static in_next_object
  variable, but which is now stored in thread local
  storage (TLS, or thread variable if this names are more
  clear for you).

This makes code thread-safe, but for sure final solution
shall be completely different. Ideally, dependency graph
shall be possible to answer on question "which object is
a motherball for this metaball". This will avoid iterating
via all the bases, objects and duplis just to get needed
motherball.

Further, metaball evaluation ideally will use the same
kind of depsgraph filtering, which will get result for
question like "which objects belongs to this group of
metaballs".

But this ideal things are to be solved in Joshua's and
mind GSoC projects.

Tested on linux (gcc and clang) and windows (msvc2008),
hopefully no compilation error will happen.

Thanks to Brecht for reviewing the change and getting
feedback for other possible ways we've dicussed!

Modified Paths:
--------------
    trunk/blender/source/blender/blenkernel/BKE_scene.h
    trunk/blender/source/blender/blenkernel/intern/mball.c
    trunk/blender/source/blender/blenkernel/intern/scene.c
    trunk/blender/source/blender/blenlib/BLI_threads.h

Modified: trunk/blender/source/blender/blenkernel/BKE_scene.h
===================================================================
--- trunk/blender/source/blender/blenkernel/BKE_scene.h	2013-07-09 08:17:14 UTC (rev 58109)
+++ trunk/blender/source/blender/blenkernel/BKE_scene.h	2013-07-09 08:23:01 UTC (rev 58110)
@@ -75,8 +75,18 @@
 void         BKE_scene_base_unlink(struct Scene *sce, struct Base *base);
 void         BKE_scene_base_deselect_all(struct Scene *sce);
 void         BKE_scene_base_select(struct Scene *sce, struct Base *selbase);
-int          BKE_scene_base_iter_next(struct Scene **scene, int val, struct Base **base, struct Object **ob);
 
+/* Scene base iteration function.
+ * Define struct here, so no need to bother with alloc/free it.
+ */
+typedef struct SceneBaseIter {
+	struct ListBase *duplilist;
+	struct DupliObject *dupob;
+	int fase;
+} SceneBaseIter;
+
+int          BKE_scene_base_iter_next(struct SceneBaseIter *iter, struct Scene **scene, int val, struct Base **base, struct Object **ob);
+
 void BKE_scene_base_flag_to_objects(struct Scene *scene);
 void BKE_scene_base_flag_from_objects(struct Scene *scene);
 

Modified: trunk/blender/source/blender/blenkernel/intern/mball.c
===================================================================
--- trunk/blender/source/blender/blenkernel/intern/mball.c	2013-07-09 08:17:14 UTC (rev 58109)
+++ trunk/blender/source/blender/blenkernel/intern/mball.c	2013-07-09 08:23:01 UTC (rev 58110)
@@ -485,14 +485,15 @@
 	MetaBall *active_mball = (MetaBall *)active_object->data;
 	int basisnr, obnr;
 	char basisname[MAX_ID_NAME], obname[MAX_ID_NAME];
-	
+	SceneBaseIter iter;
+
 	BLI_split_name_num(basisname, &basisnr, active_object->id.name + 2, '.');
 
 	/* XXX recursion check, see scene.c, just too simple code this BKE_scene_base_iter_next() */
-	if (F_ERROR == BKE_scene_base_iter_next(&sce_iter, 0, NULL, NULL))
+	if (F_ERROR == BKE_scene_base_iter_next(&iter, &sce_iter, 0, NULL, NULL))
 		return;
 	
-	while (BKE_scene_base_iter_next(&sce_iter, 1, &base, &ob)) {
+	while (BKE_scene_base_iter_next(&iter, &sce_iter, 1, &base, &ob)) {
 		if (ob->type == OB_MBALL) {
 			if (ob != active_object) {
 				BLI_split_name_num(obname, &obnr, ob->id.name + 2, '.');
@@ -529,14 +530,15 @@
 	Object *ob, *bob = basis;
 	int basisnr, obnr;
 	char basisname[MAX_ID_NAME], obname[MAX_ID_NAME];
+	SceneBaseIter iter;
 
 	BLI_split_name_num(basisname, &basisnr, basis->id.name + 2, '.');
 
 	/* XXX recursion check, see scene.c, just too simple code this BKE_scene_base_iter_next() */
-	if (F_ERROR == BKE_scene_base_iter_next(&sce_iter, 0, NULL, NULL))
+	if (F_ERROR == BKE_scene_base_iter_next(&iter, &sce_iter, 0, NULL, NULL))
 		return NULL;
 
-	while (BKE_scene_base_iter_next(&sce_iter, 1, &base, &ob)) {
+	while (BKE_scene_base_iter_next(&iter, &sce_iter, 1, &base, &ob)) {
 		if (ob->type == OB_MBALL) {
 			if (ob != bob) {
 				BLI_split_name_num(obname, &obnr, ob->id.name + 2, '.');
@@ -1655,7 +1657,8 @@
 	//float max = 0.0f;
 	int a, obnr, zero_size = 0;
 	char obname[MAX_ID_NAME];
-	
+	SceneBaseIter iter;
+
 	copy_m4_m4(obmat, ob->obmat);   /* to cope with duplicators from BKE_scene_base_iter_next */
 	invert_m4_m4(obinv, ob->obmat);
 	a = 0;
@@ -1663,8 +1666,8 @@
 	BLI_split_name_num(obname, &obnr, ob->id.name + 2, '.');
 	
 	/* make main array */
-	BKE_scene_base_iter_next(&sce_iter, 0, NULL, NULL);
-	while (BKE_scene_base_iter_next(&sce_iter, 1, &base, &bob)) {
+	BKE_scene_base_iter_next(&iter, &sce_iter, 0, NULL, NULL);
+	while (BKE_scene_base_iter_next(&iter, &sce_iter, 1, &base, &bob)) {
 
 		if (bob->type == OB_MBALL) {
 			zero_size = 0;
@@ -2225,15 +2228,16 @@
 	MetaElem *ml = NULL;
 	int basisnr, obnr;
 	char basisname[MAX_ID_NAME], obname[MAX_ID_NAME];
+	SceneBaseIter iter;
 
 	BLI_split_name_num(basisname, &basisnr, basis->id.name + 2, '.');
 	process->totelem = 0;
 
 	/* XXX recursion check, see scene.c, just too simple code this BKE_scene_base_iter_next() */
-	if (F_ERROR == BKE_scene_base_iter_next(&sce_iter, 0, NULL, NULL))
+	if (F_ERROR == BKE_scene_base_iter_next(&iter, &sce_iter, 0, NULL, NULL))
 		return;
 
-	while (BKE_scene_base_iter_next(&sce_iter, 1, &base, &ob)) {
+	while (BKE_scene_base_iter_next(&iter, &sce_iter, 1, &base, &ob)) {
 		if (ob->type == OB_MBALL) {
 			if (ob == bob) {
 				MetaBall *mb = ob->data;

Modified: trunk/blender/source/blender/blenkernel/intern/scene.c
===================================================================
--- trunk/blender/source/blender/blenkernel/intern/scene.c	2013-07-09 08:17:14 UTC (rev 58109)
+++ trunk/blender/source/blender/blenkernel/intern/scene.c	2013-07-09 08:23:01 UTC (rev 58110)
@@ -746,17 +746,16 @@
 /* used by metaballs
  * doesn't return the original duplicated object, only dupli's
  */
-int BKE_scene_base_iter_next(Scene **scene, int val, Base **base, Object **ob)
+int BKE_scene_base_iter_next(SceneBaseIter *iter, Scene **scene, int val, Base **base, Object **ob)
 {
-	static ListBase *duplilist = NULL;
-	static DupliObject *dupob;
-	static int fase = F_START, in_next_object = 0;
+	static ThreadVariable int in_next_object = 0;
 	int run_again = 1;
 	
 	/* init */
 	if (val == 0) {
-		fase = F_START;
-		dupob = NULL;
+		iter->fase = F_START;
+		iter->dupob = NULL;
+		iter->duplilist = NULL;
 		
 		/* XXX particle systems with metas+dupligroups call this recursively */
 		/* see bug #18725 */
@@ -774,11 +773,11 @@
 			run_again = 0;
 
 			/* the first base */
-			if (fase == F_START) {
+			if (iter->fase == F_START) {
 				*base = (*scene)->base.first;
 				if (*base) {
 					*ob = (*base)->object;
-					fase = F_SCENE;
+					iter->fase = F_SCENE;
 				}
 				else {
 					/* exception: empty scene */
@@ -787,20 +786,20 @@
 						if ((*scene)->base.first) {
 							*base = (*scene)->base.first;
 							*ob = (*base)->object;
-							fase = F_SCENE;
+							iter->fase = F_SCENE;
 							break;
 						}
 					}
 				}
 			}
 			else {
-				if (*base && fase != F_DUPLI) {
+				if (*base && iter->fase != F_DUPLI) {
 					*base = (*base)->next;
 					if (*base) {
 						*ob = (*base)->object;
 					}
 					else {
-						if (fase == F_SCENE) {
+						if (iter->fase == F_SCENE) {
 							/* (*scene) is finished, now do the set */
 							while ((*scene)->set) {
 								(*scene) = (*scene)->set;
@@ -816,45 +815,45 @@
 			}
 			
 			if (*base == NULL) {
-				fase = F_START;
+				iter->fase = F_START;
 			}
 			else {
-				if (fase != F_DUPLI) {
+				if (iter->fase != F_DUPLI) {
 					if ( (*base)->object->transflag & OB_DUPLI) {
 						/* groups cannot be duplicated for mballs yet, 
 						 * this enters eternal loop because of 
 						 * makeDispListMBall getting called inside of group_duplilist */
 						if ((*base)->object->dup_group == NULL) {
-							duplilist = object_duplilist((*scene), (*base)->object, FALSE);
+							iter->duplilist = object_duplilist((*scene), (*base)->object, FALSE);
 							
-							dupob = duplilist->first;
+							iter->dupob = iter->duplilist->first;
 
-							if (!dupob)
-								free_object_duplilist(duplilist);
+							if (!iter->dupob)
+								free_object_duplilist(iter->duplilist);
 						}
 					}
 				}
 				/* handle dupli's */
-				if (dupob) {
+				if (iter->dupob) {
 					
-					copy_m4_m4(dupob->ob->obmat, dupob->mat);
+					copy_m4_m4(iter->dupob->ob->obmat, iter->dupob->mat);
 					
 					(*base)->flag |= OB_FROMDUPLI;
-					*ob = dupob->ob;
-					fase = F_DUPLI;
+					*ob = iter->dupob->ob;
+					iter->fase = F_DUPLI;
 					
-					dupob = dupob->next;
+					iter->dupob = iter->dupob->next;
 				}
-				else if (fase == F_DUPLI) {
-					fase = F_SCENE;
+				else if (iter->fase == F_DUPLI) {
+					iter->fase = F_SCENE;
 					(*base)->flag &= ~OB_FROMDUPLI;
 					
-					for (dupob = duplilist->first; dupob; dupob = dupob->next) {
-						copy_m4_m4(dupob->ob->obmat, dupob->omat);
+					for (iter->dupob = iter->duplilist->first; iter->dupob; iter->dupob = iter->dupob->next) {
+						copy_m4_m4(iter->dupob->ob->obmat, iter->dupob->omat);
 					}
 					
-					free_object_duplilist(duplilist);
-					duplilist = NULL;
+					free_object_duplilist(iter->duplilist);
+					iter->duplilist = NULL;
 					run_again = 1;
 				}
 			}
@@ -870,7 +869,7 @@
 	/* reset recursion test */
 	in_next_object = 0;
 	
-	return fase;
+	return iter->fase;
 }
 
 Object *BKE_scene_camera_find(Scene *sc)

Modified: trunk/blender/source/blender/blenlib/BLI_threads.h
===================================================================
--- trunk/blender/source/blender/blenlib/BLI_threads.h	2013-07-09 08:17:14 UTC (rev 58109)
+++ trunk/blender/source/blender/blenlib/BLI_threads.h	2013-07-09 08:23:01 UTC (rev 58110)
@@ -182,6 +182,13 @@
 void BLI_thread_queue_wait_finish(ThreadQueue *queue);
 void BLI_thread_queue_nowait(ThreadQueue *queue);
 
+/* Thread Local Storage */
+#ifdef _MSC_VER
+#  define ThreadVariable  __declspec(thread)
+#else
+#  define ThreadVariable  __thread
+#endif
+
 #ifdef __cplusplus
 }
 #endif




More information about the Bf-blender-cvs mailing list