From 10b7f835854f46ac390fdb6954d312a6b0ba30e9 Mon Sep 17 00:00:00 2001
From: Andrej Rode <mail@andrejro.de>
Date: Thu, 13 Apr 2017 23:38:12 -0700
Subject: runtime: add barrier to synchronize block startup

---
 gnuradio-runtime/include/gnuradio/thread/thread.h |  4 ++++
 gnuradio-runtime/lib/scheduler_tpb.cc             | 20 ++++++++++++--------
 gnuradio-runtime/lib/tpb_thread_body.cc           |  3 ++-
 gnuradio-runtime/lib/tpb_thread_body.h            |  3 ++-
 4 files changed, 20 insertions(+), 10 deletions(-)

(limited to 'gnuradio-runtime')

diff --git a/gnuradio-runtime/include/gnuradio/thread/thread.h b/gnuradio-runtime/include/gnuradio/thread/thread.h
index a58d172867..20a94cba52 100644
--- a/gnuradio-runtime/include/gnuradio/thread/thread.h
+++ b/gnuradio-runtime/include/gnuradio/thread/thread.h
@@ -27,6 +27,8 @@
 #include <boost/thread/mutex.hpp>
 #include <boost/thread/locks.hpp>
 #include <boost/thread/condition_variable.hpp>
+#include <boost/thread/barrier.hpp>
+#include <boost/shared_ptr.hpp>
 #include <vector>
 
 #if defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
@@ -46,6 +48,8 @@ namespace gr {
     typedef boost::mutex                     mutex;
     typedef boost::unique_lock<boost::mutex> scoped_lock;
     typedef boost::condition_variable        condition_variable;
+    typedef boost::barrier                   barrier;
+    typedef boost::shared_ptr<barrier>       barrier_sptr;
 
     /*! \brief a system-dependent typedef for the underlying thread type.
      */
diff --git a/gnuradio-runtime/lib/scheduler_tpb.cc b/gnuradio-runtime/lib/scheduler_tpb.cc
index 0319a43a88..fe593670f8 100644
--- a/gnuradio-runtime/lib/scheduler_tpb.cc
+++ b/gnuradio-runtime/lib/scheduler_tpb.cc
@@ -26,6 +26,7 @@
 #include "scheduler_tpb.h"
 #include "tpb_thread_body.h"
 #include <gnuradio/thread/thread_body_wrapper.h>
+#include <boost/make_shared.hpp>
 #include <sstream>
 
 namespace gr {
@@ -34,14 +35,15 @@ namespace gr {
   {
     block_sptr d_block;
     int d_max_noutput_items;
+    thread::barrier_sptr d_start_sync;
 
   public:
-    tpb_container(block_sptr block, int max_noutput_items)
-      : d_block(block), d_max_noutput_items(max_noutput_items) {}
+    tpb_container(block_sptr block, int max_noutput_items, thread::barrier_sptr start_sync)
+      : d_block(block), d_max_noutput_items(max_noutput_items), d_start_sync(start_sync) {}
 
     void operator()()
     {
-      tpb_thread_body body(d_block, d_max_noutput_items);
+      tpb_thread_body body(d_block, d_start_sync, d_max_noutput_items);
     }
   };
 
@@ -71,6 +73,9 @@ namespace gr {
       blocks[i]->detail()->set_done(false);
     }
 
+    thread::barrier_sptr start_sync =
+      boost::make_shared<thread::barrier>(blocks.size()+1);
+
     // Fire off a thead for each block
 
     for(size_t i = 0; i < blocks.size(); i++) {
@@ -84,12 +89,11 @@ namespace gr {
       else {
         block_max_noutput_items = max_noutput_items;
       }
-
-      d_threads.create_thread(
-	    gr::thread::thread_body_wrapper<tpb_container>
-            (tpb_container(blocks[i], block_max_noutput_items),
-             name.str()));
+      d_threads.create_thread(thread::thread_body_wrapper<tpb_container>(
+          tpb_container(blocks[i], block_max_noutput_items, start_sync),
+          name.str()));
     }
+    start_sync->wait();
   }
 
   scheduler_tpb::~scheduler_tpb()
diff --git a/gnuradio-runtime/lib/tpb_thread_body.cc b/gnuradio-runtime/lib/tpb_thread_body.cc
index 93591feee2..72fc671c40 100644
--- a/gnuradio-runtime/lib/tpb_thread_body.cc
+++ b/gnuradio-runtime/lib/tpb_thread_body.cc
@@ -32,7 +32,7 @@
 
 namespace gr {
 
-  tpb_thread_body::tpb_thread_body(block_sptr block, int max_noutput_items)
+  tpb_thread_body::tpb_thread_body(block_sptr block, gr::thread::barrier_sptr start_sync, int max_noutput_items)
     : d_exec(block, max_noutput_items)
   {
     //std::cerr << "tpb_thread_body: " << block << std::endl;
@@ -92,6 +92,7 @@ namespace gr {
     // make sure our block isnt finished
     block->clear_finished();
 
+    start_sync->wait();
     while(1) {
       tpb_loop_top:
       boost::this_thread::interruption_point();
diff --git a/gnuradio-runtime/lib/tpb_thread_body.h b/gnuradio-runtime/lib/tpb_thread_body.h
index 9859b125dd..c500582cf3 100644
--- a/gnuradio-runtime/lib/tpb_thread_body.h
+++ b/gnuradio-runtime/lib/tpb_thread_body.h
@@ -24,6 +24,7 @@
 #include <gnuradio/api.h>
 #include <gnuradio/block.h>
 #include <gnuradio/block_detail.h>
+#include <gnuradio/thread/thread.h>
 #include "block_executor.h"
 
 namespace gr {
@@ -40,7 +41,7 @@ namespace gr {
     block_executor d_exec;
 
   public:
-    tpb_thread_body(block_sptr block, int max_noutput_items=100000);
+    tpb_thread_body(block_sptr block,  thread::barrier_sptr start_sync, int max_noutput_items=100000);
     ~tpb_thread_body();
   };
 
-- 
cgit v1.2.3