[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [31417] branches/particles-2010: Fixed a multithreading bug that lead to freeze when using more than 2 threads .
Lukas Toenne
lukas.toenne at googlemail.com
Tue Aug 17 15:28:12 CEST 2010
Revision: 31417
http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=31417
Author: lukastoenne
Date: 2010-08-17 15:28:12 +0200 (Tue, 17 Aug 2010)
Log Message:
-----------
Fixed a multithreading bug that lead to freeze when using more than 2 threads. This could happen because the operator stack could be depleted by 3 threads (in simple setups), while the others were still waiting for jobs and are never woken up. Keeping the mutex locked between ending a job a executing the next operator node and triggering the condition after that resolves the problem.
Modified Paths:
--------------
branches/particles-2010/release/scripts/ui/properties_data_particleset.py
branches/particles-2010/source/blender/blenkernel/intern/particleset.c
branches/particles-2010/source/blender/makesdna/DNA_node_types.h
branches/particles-2010/source/blender/makesrna/intern/rna_nodetree.c
branches/particles-2010/source/blender/nodes/intern/node_tree_simulation.c
Modified: branches/particles-2010/release/scripts/ui/properties_data_particleset.py
===================================================================
--- branches/particles-2010/release/scripts/ui/properties_data_particleset.py 2010-08-17 13:14:41 UTC (rev 31416)
+++ branches/particles-2010/release/scripts/ui/properties_data_particleset.py 2010-08-17 13:28:12 UTC (rev 31417)
@@ -21,7 +21,7 @@
from rna_prop_ui import PropertyPanel
-class DataButtonsPanel(bpy.types.Panel):
+class DataButtonsPanel():
bl_space_type = 'PROPERTIES'
bl_region_type = 'WINDOW'
bl_context = "data"
@@ -31,7 +31,7 @@
return context.particleset
-class DATA_PT_context_particleset(DataButtonsPanel):
+class DATA_PT_context_particleset(DataButtonsPanel, bpy.types.Panel):
bl_label = ""
bl_show_header = False
@@ -48,11 +48,11 @@
layout.template_ID(space, "pin_id")
-class DATA_PT_custom_props_particleset(DataButtonsPanel, PropertyPanel):
+class DATA_PT_custom_props_particleset(DataButtonsPanel, PropertyPanel, bpy.types.Panel):
_context_path = "object.data"
-class DATA_PT_particleset(DataButtonsPanel):
+class DATA_PT_particleset(DataButtonsPanel, bpy.types.Panel):
bl_label = "Particle Set"
def draw(self, context):
@@ -85,23 +85,11 @@
col.prop(pp, "offset")
-classes = [
- DATA_PT_context_particleset,
- DATA_PT_particleset,
-
- DATA_PT_custom_props_particleset]
-
-
def register():
- register = bpy.types.register
- for cls in classes:
- register(cls)
+ pass
-
def unregister():
- unregister = bpy.types.unregister
- for cls in classes:
- unregister(cls)
+ pass
if __name__ == "__main__":
register()
Modified: branches/particles-2010/source/blender/blenkernel/intern/particleset.c
===================================================================
--- branches/particles-2010/source/blender/blenkernel/intern/particleset.c 2010-08-17 13:14:41 UTC (rev 31416)
+++ branches/particles-2010/source/blender/blenkernel/intern/particleset.c 2010-08-17 13:28:12 UTC (rev 31417)
@@ -751,6 +751,9 @@
pset_add_default_properties(pset);
+ /* add a nodetree modifier by default */
+ /* TODO */
+
return pset;
}
Modified: branches/particles-2010/source/blender/makesdna/DNA_node_types.h
===================================================================
--- branches/particles-2010/source/blender/makesdna/DNA_node_types.h 2010-08-17 13:14:41 UTC (rev 31416)
+++ branches/particles-2010/source/blender/makesdna/DNA_node_types.h 2010-08-17 13:28:12 UTC (rev 31417)
@@ -120,6 +120,7 @@
#define SOCK_BOOL 5
#define SOCK_INT 6
#define SOCK_FLOAT 7
+#define SOCK_STRING 8
/* sock->flag, first bit is select */
/* hidden is user defined, to hide unused */
Modified: branches/particles-2010/source/blender/makesrna/intern/rna_nodetree.c
===================================================================
--- branches/particles-2010/source/blender/makesrna/intern/rna_nodetree.c 2010-08-17 13:14:41 UTC (rev 31416)
+++ branches/particles-2010/source/blender/makesrna/intern/rna_nodetree.c 2010-08-17 13:28:12 UTC (rev 31417)
@@ -99,6 +99,8 @@
return &RNA_FloatNodeSocket;
case SOCK_BOOL:
return &RNA_BoolNodeSocket;
+ case SOCK_STRING:
+ return &RNA_StringNodeSocket;
default:
return &RNA_UnknownType;
}
@@ -2351,6 +2353,28 @@
RNA_def_property_update(prop, NC_NODE|NA_EDITED, "rna_NodeSocket_update");
}
+static void rna_def_node_socket_string(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ srna = RNA_def_struct(brna, "StringNodeSocket", NULL);
+ RNA_def_struct_ui_text(srna, "String Node Socket", "Input or output socket of a node");
+ RNA_def_struct_sdna(srna, "bNodeSocket");
+ RNA_def_struct_ui_icon(srna, ICON_PLUG);
+ RNA_def_struct_path_func(srna, "rna_NodeSocket_path");
+
+ prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE);
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_ui_text(prop, "Name", "Socket name");
+ RNA_def_struct_name_property(srna, prop);
+
+ prop = RNA_def_property(srna, "default_value", PROP_STRING, PROP_NONE);
+ RNA_def_property_string_sdna(prop, NULL, "ns.data");
+ RNA_def_property_ui_text(prop, "Default Value", "Default value of the socket when no link is attached");
+ RNA_def_property_update(prop, NC_NODE|NA_EDITED, "rna_NodeSocket_update");
+}
+
static void rna_def_node(BlenderRNA *brna)
{
StructRNA *srna;
@@ -2434,6 +2458,7 @@
rna_def_node_socket_int(brna);
rna_def_node_socket_float(brna);
rna_def_node_socket_bool(brna);
+ rna_def_node_socket_string(brna);
rna_def_node(brna);
rna_def_shader_node(brna);
rna_def_compositor_node(brna);
Modified: branches/particles-2010/source/blender/nodes/intern/node_tree_simulation.c
===================================================================
--- branches/particles-2010/source/blender/nodes/intern/node_tree_simulation.c 2010-08-17 13:14:41 UTC (rev 31416)
+++ branches/particles-2010/source/blender/nodes/intern/node_tree_simulation.c 2010-08-17 13:28:12 UTC (rev 31417)
@@ -367,15 +367,13 @@
return hasnewjobs;
}
+/* Not threadsafe! ctx->mutex must be locked during this function! */
static SimNodeJob *node_thread_find_job(SimNodeThreadContext *ctx)
{
SimNodeJob *job=NULL;
SimNodeInstance *node;
int n;
- /* TODO it might be beneficial to use RW lock here or even per-node mutexes if searching for jobs takes significant time */
- pthread_mutex_lock(&ctx->mutex);
-
while (1) {
#if 0
{
@@ -509,14 +507,13 @@
else
break;
}
- pthread_mutex_unlock(&ctx->mutex);
return job;
}
+/* Not threadsafe! ctx->mutex must be locked during this function! */
static void node_thread_suspend_job(SimNodeThreadContext *ctx, SimNodeJob *job)
{
- pthread_mutex_lock(&ctx->mutex);
if (job->state == SIM_JOB_RUNNING) {
job->state = SIM_JOB_SUSPENDED;
++job->execlevel;
@@ -541,12 +538,11 @@
if (ctx->active <= 0)
pthread_cond_signal(&ctx->cond);
}
- pthread_mutex_unlock(&ctx->mutex);
}
+/* Not threadsafe! ctx->mutex must be locked during this function! */
static void node_thread_finish_job(SimNodeThreadContext *ctx, SimNodeJob *job)
{
- pthread_mutex_lock(&ctx->mutex);
if (job->state == SIM_JOB_RUNNING || job->state == SIM_JOB_CANCEL) {
job->state = SIM_JOB_DONE;
if (job->node->node->typeinfo->sim_endjobfunc)
@@ -562,12 +558,11 @@
if (ctx->active <= 0)
pthread_cond_signal(&ctx->cond);
}
- pthread_mutex_unlock(&ctx->mutex);
}
+/* Not threadsafe! ctx->mutex must be locked during this function! */
static void node_thread_cancel_job(SimNodeThreadContext *ctx, SimNodeJob *job)
{
- pthread_mutex_lock(&ctx->mutex);
if (job->state == SIM_JOB_RUNNING) {
job->state = SIM_JOB_CANCEL;
}
@@ -583,16 +578,15 @@
/* TODO decrease branch counters and free data if possible */
}
- pthread_mutex_unlock(&ctx->mutex);
}
+/* Not threadsafe! ctx->mutex must be locked during this function! */
static void node_thread_cancel_all_jobs(SimNodeThreadContext *ctx)
{
SimNodeInstance *node;
SimNodeJob *job;
int n;
- pthread_mutex_lock(&ctx->mutex);
for (n=0, node=ctx->nodestack; n < ctx->totnode; ++n, ++node) {
for (job=node->jobs.first; job; job=job->next) {
if (job->state == SIM_JOB_RUNNING) {
@@ -612,7 +606,6 @@
}
}
}
- pthread_mutex_unlock(&ctx->mutex);
}
int sim_insert_output_batch(SimNodeThreadContext *ctx, SimNodeInstance *node, SimNodeSocketInstance *sock, SimNodeBatch *batch)
@@ -734,6 +727,7 @@
}
}
+/* Not threadsafe! ctx->mutex must be locked during this function! */
static int node_thread_exec_op(SimNodeThreadContext *ctx)
{
// bNodeTree *ntree= ctx->sim->ntmd->nodetree;
@@ -741,8 +735,6 @@
SimNodeOperator *cur_op, *next_op;
int opsock, suspend;
- pthread_mutex_lock(&ctx->mutex);
-
cur_op = (SimNodeOperator*)ctx->opstack.last;
if (cur_op) {
/* execute operator and update execution stack */
@@ -776,8 +768,6 @@
cur_op = (SimNodeOperator*)ctx->opstack.last;
}
- pthread_mutex_unlock(&ctx->mutex);
-
return (cur_op != 0);
}
@@ -794,9 +784,10 @@
* access the next/prev pointers or the state (which are modified when other jobs are added/removed).
* These need locking of the context mutex first. Could be made more fool-proof later.
*/
-// printf("Thread %d/%d searching job:\n", thread->num, ctx->totthread);
+ pthread_mutex_lock(&ctx->mutex);
job = node_thread_find_job(ctx);
if (job != NULL) {
+ pthread_mutex_unlock(&ctx->mutex); /* unlock mutex during job execution */
#if 0
/* ========= DEBUG ========= */
{
@@ -875,13 +866,19 @@
/* ========================= */
#endif
+ pthread_mutex_lock(&ctx->mutex);
if (suspend == NODE_EXEC_SUSPEND)
node_thread_suspend_job(ctx, job);
else
node_thread_finish_job(ctx, job);
+ pthread_mutex_unlock(&ctx->mutex);
}
else {
- if (!node_thread_exec_op(ctx))
+ int has_op;
+ has_op = node_thread_exec_op(ctx);
+ pthread_cond_signal(&ctx->cond); /* wake threads to look for new jobs or exit */
+ pthread_mutex_unlock(&ctx->mutex);
+ if (!has_op)
break;
}
}
More information about the Bf-blender-cvs
mailing list