Merged jcorgan/sfg r4097:4124 into trunk, fixing hier_block2 threading issues.
authorjcorgan <jcorgan@221aa14e-8319-0410-a670-987f0aec2ac5>
Mon, 18 Dec 2006 04:35:19 +0000 (04:35 +0000)
committerjcorgan <jcorgan@221aa14e-8319-0410-a670-987f0aec2ac5>
Mon, 18 Dec 2006 04:35:19 +0000 (04:35 +0000)
git-svn-id: http://gnuradio.org/svn/gnuradio/trunk@4126 221aa14e-8319-0410-a670-987f0aec2ac5

gnuradio-core/src/lib/runtime/gr_runtime.cc
gnuradio-core/src/lib/runtime/gr_runtime_impl.cc
gnuradio-core/src/lib/runtime/gr_runtime_impl.h
gnuradio-core/src/lib/runtime/gr_simple_flowgraph_detail.cc
gnuradio-core/src/lib/runtime/gr_simple_flowgraph_detail.h
gnuradio-examples/c++/dialtone/dialtone.cc
gnuradio-examples/python/audio/dial_tone2.py

index 926e878575a2e317fa0fe9420c4c4cc3512f7cc8..93f78fea8567d0edae7cf3c806e2ddbe9da77921 100644 (file)
 
 #include <gr_runtime.h>
 #include <gr_runtime_impl.h>
+#include <gr_local_sighandler.h>
 #include <iostream>
 
+static gr_runtime *s_runtime = 0;
+
 gr_runtime_sptr 
 gr_make_runtime(gr_hier_block2_sptr top_block)
 {
@@ -37,16 +40,29 @@ gr_make_runtime(gr_hier_block2_sptr top_block)
 gr_runtime::gr_runtime(gr_hier_block2_sptr top_block)
 {
     d_impl = new gr_runtime_impl(top_block);
+    s_runtime = this;
 }
   
 gr_runtime::~gr_runtime()
 {
+    s_runtime = 0; // we don't own this
     delete d_impl;
 }
 
+// HACK: This prevents using more than one gr_runtime instance
+static void 
+runtime_sigint_handler(int signum)
+{
+
+    if (s_runtime)
+        s_runtime->stop();
+}
+
 void 
 gr_runtime::start()
 {
+    gr_local_sighandler sigint(SIGINT, runtime_sigint_handler);
+
     d_impl->start();
 }
 
@@ -59,12 +75,16 @@ gr_runtime::stop()
 void 
 gr_runtime::wait()
 {
+    gr_local_sighandler sigint(SIGINT, runtime_sigint_handler);
+
     d_impl->wait();
 }
 
 void 
 gr_runtime::run()
 {
-    start();
-    wait();
+    gr_local_sighandler sigint(SIGINT, runtime_sigint_handler);
+
+    d_impl->start();
+    d_impl->wait();
 }
index ffc897b8ba2ff010d349953368e13ead85acf23a..dcd904a01cffaa3a9628835f0adbd89b24cab47e 100644 (file)
 #include <gr_simple_flowgraph.h>
 #include <gr_hier_block2.h>
 #include <gr_hier_block2_detail.h>
+#include <signal.h>
 #include <stdexcept>
 #include <iostream>
 
-gr_runtime_impl::gr_runtime_impl(gr_hier_block2_sptr top_block) :
-d_running(false),
-d_top_block(top_block),
-d_sfg(gr_make_simple_flowgraph()),
-d_graphs()
+gr_runtime_impl::gr_runtime_impl(gr_hier_block2_sptr top_block) 
+  : d_running(false),
+    d_top_block(top_block),
+    d_sfg(gr_make_simple_flowgraph())
 {
 }
 
@@ -66,7 +66,7 @@ gr_runtime_impl::start()
     d_threads.clear();
     for (std::vector<gr_block_vector_t>::iterator p = d_graphs.begin();
          p != d_graphs.end(); p++) {
-        gr_scheduler_thread_sptr thread = gr_make_scheduler_thread(*p);
+        gr_scheduler_thread *thread = new gr_scheduler_thread(*p);
         thread->start();
         d_threads.push_back(thread);
     }
@@ -78,9 +78,8 @@ gr_runtime_impl::stop()
     if (!d_running)
         throw std::runtime_error("not running");
 
-    for (gr_scheduler_thread_viter_t p = d_threads.begin(); 
-         p != d_threads.end(); p++)
-        (*p)->stop();
+    for (gr_scheduler_thread_viter_t p = d_threads.begin(); p != d_threads.end(); p++)
+        (*p)->stop(); 
 
     d_running = false;
 }
@@ -88,19 +87,12 @@ gr_runtime_impl::stop()
 void
 gr_runtime_impl::wait()
 {
-    for (gr_scheduler_thread_viter_t p = d_threads.begin(); 
-         p != d_threads.end(); p++) {
-        while(1) {
-            (*p)->join(NULL);
-            if (!(*p)->state() == omni_thread::STATE_TERMINATED)
-                break;
-        }
-    }
-}
+    void *dummy_status; // don't ever dereference this
 
-gr_scheduler_thread_sptr gr_make_scheduler_thread(gr_block_vector_t graph)
-{
-    return gr_scheduler_thread_sptr(new gr_scheduler_thread(graph));
+    for (gr_scheduler_thread_viter_t p = d_threads.begin(); p != d_threads.end(); p++) {
+        (*p)->join(&dummy_status); // pthreads will self-delete, so pointer is now dead
+        (*p) = 0; // FIXME: switch to stl::list and actually remove from container
+    }
 }
 
 gr_scheduler_thread::gr_scheduler_thread(gr_block_vector_t graph) :
@@ -118,8 +110,19 @@ void gr_scheduler_thread::start()
     start_undetached();
 }
 
-void *gr_scheduler_thread::run_undetached(void *arg)
+void *
+gr_scheduler_thread::run_undetached(void *arg)
 {
+    // First code to run in new thread context
+
+    // Mask off SIGINT in this thread to gaurantee mainline thread gets signal
+    sigset_t old_set;
+    sigset_t new_set;
+    sigfillset(&new_set);
+    sigdelset(&new_set, SIGINT);
+    sigprocmask(SIG_BLOCK, &new_set, &old_set);
+
+    // Run the single-threaded scheduler
     d_sts->run();
     return 0;
 }
index 54977ef97470bffafd6793bccfc17696449a77e8..e694467196bf0861f4c00337a847ec8789b02705 100644 (file)
 #include <omnithread.h>
 #include <gr_single_threaded_scheduler.h>
 
+// omnithread calls delete on itself after thread exits, so can't use shared ptr
 class gr_scheduler_thread;
-typedef boost::shared_ptr<gr_scheduler_thread> gr_scheduler_thread_sptr;
-typedef std::vector<gr_scheduler_thread_sptr> gr_scheduler_thread_vector_t;
-typedef std::vector<gr_scheduler_thread_sptr>::iterator gr_scheduler_thread_viter_t;
-
-gr_scheduler_thread_sptr gr_make_scheduler_thread(gr_block_vector_t graph);
+typedef std::vector<gr_scheduler_thread *> gr_scheduler_thread_vector_t;
+typedef gr_scheduler_thread_vector_t::iterator gr_scheduler_thread_viter_t;
 
 class gr_scheduler_thread : public omni_thread
 {
 private:
-    gr_scheduler_thread(gr_block_vector_t graph);
-    friend gr_scheduler_thread_sptr gr_make_scheduler_thread(gr_block_vector_t graph);
-
     gr_single_threaded_scheduler_sptr d_sts;    
 
 public:
+    gr_scheduler_thread(gr_block_vector_t graph);
     ~gr_scheduler_thread();
+
     virtual void *run_undetached(void *arg);
     void start();
     void stop();
index 36dc0bc40e5c693b51b5a611e533d7650f80deb8..0c9c9b707933f78b7af0640c42c2c101ed2ac367 100644 (file)
@@ -110,8 +110,8 @@ gr_simple_flowgraph_detail::connect(const std::string &src_name, int src_port,
     gr_block_sptr dst_block = lookup_block(dst_name);
 
     if (GR_SIMPLE_FLOWGRAPH_DETAIL_DEBUG)
-       std::cout << "Connecting " << src_name << ":" << src_port << "->"
-              << dst_name << ":" << dst_port << std::endl;
+        std::cout << "Connecting " << src_name << ":" << src_port << "->"
+                  << dst_name << ":" << dst_port << std::endl;
 
     if (!src_block)
         throw std::invalid_argument("unknown src name");
@@ -291,8 +291,8 @@ gr_simple_flowgraph_detail::setup_connections()
         gr_edge_vector_t in_edges = calc_upstream_edges(p->first);
 
         if (GR_SIMPLE_FLOWGRAPH_DETAIL_DEBUG)
-           if (in_edges.size() > 0)
-               std::cout << "Connecting inputs to " << p->first << "..." << std::endl;
+               if (in_edges.size() > 0)
+                   std::cout << "Connecting inputs to " << p->first << "..." << std::endl;
 
         // For each edge that feeds into it
         for (gr_edge_viter_t e = in_edges.begin(); e != in_edges.end(); e++) {
@@ -485,28 +485,12 @@ gr_simple_flowgraph_detail::calc_adjacent_blocks(gr_block_sptr block, gr_block_v
     return result;
 }
 
-void
-gr_simple_flowgraph_detail::dump_block_vector(gr_block_vector_t blocks)
-{
-    for (gr_block_viter_t p = blocks.begin(); p != blocks.end(); p++) {
-        std::cout << (*p) << std::endl;
-    }
-}
-
 gr_block_vector_t
 gr_simple_flowgraph_detail::topological_sort(gr_block_vector_t &blocks)
 {
     gr_block_vector_t result, tmp;
-    std::cout << "Before source sort: " << std::endl;
-    dump_block_vector(blocks);
-    std::cout << std::endl;
-
     tmp = sort_sources_first(blocks);
 
-    std::cout << "After source sort: " << std::endl;
-    dump_block_vector(tmp);
-    std::cout << std::endl;
-
     // Start 'em all white
     for (gr_block_viter_t p = tmp.begin(); p != tmp.end(); p++)
         (*p)->detail()->set_color(gr_block_detail::WHITE);
@@ -518,10 +502,6 @@ gr_simple_flowgraph_detail::topological_sort(gr_block_vector_t &blocks)
 
     reverse(result.begin(), result.end());
 
-    std::cout << "After dfs: " << std::endl;
-    dump_block_vector(result);
-    std::cout << std::endl;
-
     return result;
 }
 
@@ -557,18 +537,15 @@ gr_simple_flowgraph_detail::topological_dfs_visit(gr_block_sptr block, gr_block_
 {
     block->detail()->set_color(gr_block_detail::GREY);
 
-    gr_block_vector_t ds_blocks = calc_downstream_blocks(lookup_name(block));
-    std::cout << "Downstream blocks of " << block << ":" << std::endl;
-    dump_block_vector(ds_blocks);
+    gr_block_vector_t blocks(calc_downstream_blocks(lookup_name(block)));
 
-    gr_block_vector_t blocks(ds_blocks);
     for (gr_block_viter_t p = blocks.begin(); p != blocks.end(); p++) {
         switch ((*p)->detail()->color()) {
-            case gr_block_detail::WHITE:            // (u, v) is a tree edge
+            case gr_block_detail::WHITE:           
                 topological_dfs_visit(*p, output);
                 break;
 
-            case gr_block_detail::GREY:             // (u, v) is a back edge - not a DAG
+            case gr_block_detail::GREY:            
                 throw std::runtime_error("flow graph has loops!");
 
             case gr_block_detail::BLACK:
@@ -577,7 +554,6 @@ gr_simple_flowgraph_detail::topological_dfs_visit(gr_block_sptr block, gr_block_
             default:
                 throw std::runtime_error("invalid color on block!");
         }
-
     }
 
     block->detail()->set_color(gr_block_detail::BLACK);
index d4812b6159439b217f1739cd90911c38f5b87883..2df1575ad41bceafcb76728468b44928c3cfd3df 100644 (file)
@@ -113,7 +113,6 @@ private:
     bool source_p(gr_block_sptr block);
     gr_block_vector_t sort_sources_first(gr_block_vector_t &blocks);
     void topological_dfs_visit(gr_block_sptr block, gr_block_vector_t &output);
-    void dump_block_vector(gr_block_vector_t blocks);
         
 public:
     ~gr_simple_flowgraph_detail();
index 08ecccf75125a62472925dd3bdc4f389231bf2a0..0debb2856194f53e836f5a0112e78ec97d40324f 100644 (file)
@@ -36,8 +36,8 @@ gr_hier_block2("dialtone",
               gr_make_io_signature(0,0,0),
               gr_make_io_signature(0,0,0))
 {
-    define_component("source0", gr_make_sig_source_f(48000, GR_SIN_WAVE, 350, 0.5));
-    define_component("source1", gr_make_sig_source_f(48000, GR_SIN_WAVE, 440, 0.5));
+    define_component("source0", gr_make_sig_source_f(48000, GR_SIN_WAVE, 350, 0.1));
+    define_component("source1", gr_make_sig_source_f(48000, GR_SIN_WAVE, 440, 0.1));
     define_component("sink", audio_alsa_make_sink(48000));
 
     connect("source0", 0, "sink", 0);
index a91c6ff4d65b4825ad50a86d14f330ee0a6a47a6..5881f06f7e05d0cee4a28cbddf84149e68d34f3b 100755 (executable)
@@ -55,7 +55,7 @@ if __name__ == '__main__':
     top_block = dial_tone()
     runtime = gr.runtime(top_block)
 
-    try:
-       runtime.run()
+    try:    
+        runtime.run()
     except KeyboardInterrupt:
-       runtime.stop()
+        pass