> We append a patch that lets TBB wait for the task to complete (using
> tbb::Task::wait_for_all() at the correct place). The only restriction
> TBB seems to set is that wait_for_all is called only once. With this
> patch, everything is fine on our machines.
The patch was still buggy - in case a task finished before calling
join(), it would not shut down the task properly. This should be fixed
in the new patch.
Best,
Katharina and Martin
Index: include/deal.II/base/thread_management.h
===================================================================
--- include/deal.II/base/thread_management.h (revision 22834)
+++ include/deal.II/base/thread_management.h (working copy)
@@ -3692,25 +3692,6 @@
// and put the return value
// into the proper place
call (task_descriptor.function, task_descriptor.ret_val);
-
- // indicate that the task
- // has finished, both
- // through the flag and
- // through the mutex that
- // was locked before we
- // started and that now
- // needs to be
- // released. this may
- // also wake up all
- // threads that may be
- // waiting for the task's
- // demise by blocking on
- // completion_mutex.acquire()
- // in
- // TaskDescriptor::join().
- task_descriptor.task_is_done = true;
- task_descriptor.completion_mutex.release ();
-
return 0;
}
@@ -3798,19 +3779,6 @@
*/
bool task_is_done;
- /**
- * Mutex used to indicate
- * when the task is done. It
- * is locked before the task
- * is spawned; the join()
- * function tries to acquire
- * it, but that will fail
- * unless the task has
- * unlocked it, which it does
- * upon completion.
- */
- mutable ThreadMutex completion_mutex;
-
public:
/**
@@ -3851,7 +3819,7 @@
* Queue up the task to the
* scheduler. We need to do
* this in a separate
- * function since we the new
+ * function since the new
* tasks needs to access
* objects from the current
* object and that can only
@@ -3894,11 +3862,6 @@
void
TaskDescriptor<RT>::queue_task ()
{
- // lock the mutex. it will
- // become unlocked when the
- // task is done
- completion_mutex.acquire ();
-
// use the pattern described in
// the TBB book on pages
// 230/231 ("Start a large task
@@ -3958,7 +3921,6 @@
// explicitly destroy the empty
// task object
Assert (task != 0, ExcInternalError());
- task->wait_for_all ();
task->destroy (*task);
}
@@ -3968,23 +3930,17 @@
void
TaskDescriptor<RT>::join ()
{
- // use Schmidt's double checking
- // pattern: if thread has already
- // indicated that it is done, then
- // return immediately
- if (task_is_done)
+ // if the task is already done, just
+ // return. this makes sure we call
+ // tbb::Task::wait_for_all() exactly
+ // once
+ if (task_is_done == true)
return;
- // acquire the lock; this can
- // only succeed when the task
- // is done
- completion_mutex.acquire ();
-
- // release it again; at this
- // point the task must have
- // finished
- completion_mutex.release ();
- Assert (task_is_done == true, ExcInternalError());
+ // let TBB wait for the task to
+ // complete. TBB will make sure that it
+ // ends properly.
+ task->wait_for_all();
}
_______________________________________________
dealii mailing list http://poisson.dealii.org/mailman/listinfo/dealii