summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjcorgan2006-12-18 04:35:19 +0000
committerjcorgan2006-12-18 04:35:19 +0000
commit95144e53f0285d9e5ea897348030a33c18773b60 (patch)
tree6b75ec33498b91cadf3e25ba90d9ee4970e8617d
parent88c16d7192ccf1caf14c2417959ab675b1f6a79e (diff)
downloadgnuradio-95144e53f0285d9e5ea897348030a33c18773b60.tar.gz
gnuradio-95144e53f0285d9e5ea897348030a33c18773b60.tar.bz2
gnuradio-95144e53f0285d9e5ea897348030a33c18773b60.zip
Merged jcorgan/sfg r4097:4124 into trunk, fixing hier_block2 threading issues.
git-svn-id: http://gnuradio.org/svn/gnuradio/trunk@4126 221aa14e-8319-0410-a670-987f0aec2ac5
-rw-r--r--gnuradio-core/src/lib/runtime/gr_runtime.cc24
-rw-r--r--gnuradio-core/src/lib/runtime/gr_runtime_impl.cc47
-rw-r--r--gnuradio-core/src/lib/runtime/gr_runtime_impl.h13
-rw-r--r--gnuradio-core/src/lib/runtime/gr_simple_flowgraph_detail.cc38
-rw-r--r--gnuradio-core/src/lib/runtime/gr_simple_flowgraph_detail.h1
-rw-r--r--gnuradio-examples/c++/dialtone/dialtone.cc4
-rwxr-xr-xgnuradio-examples/python/audio/dial_tone2.py6
7 files changed, 64 insertions, 69 deletions
diff --git a/gnuradio-core/src/lib/runtime/gr_runtime.cc b/gnuradio-core/src/lib/runtime/gr_runtime.cc
index 926e87857..93f78fea8 100644
--- a/gnuradio-core/src/lib/runtime/gr_runtime.cc
+++ b/gnuradio-core/src/lib/runtime/gr_runtime.cc
@@ -26,8 +26,11 @@
#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();
}
diff --git a/gnuradio-core/src/lib/runtime/gr_runtime_impl.cc b/gnuradio-core/src/lib/runtime/gr_runtime_impl.cc
index ffc897b8b..dcd904a01 100644
--- a/gnuradio-core/src/lib/runtime/gr_runtime_impl.cc
+++ b/gnuradio-core/src/lib/runtime/gr_runtime_impl.cc
@@ -30,14 +30,14 @@
#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;
}
diff --git a/gnuradio-core/src/lib/runtime/gr_runtime_impl.h b/gnuradio-core/src/lib/runtime/gr_runtime_impl.h
index 54977ef97..e69446719 100644
--- a/gnuradio-core/src/lib/runtime/gr_runtime_impl.h
+++ b/gnuradio-core/src/lib/runtime/gr_runtime_impl.h
@@ -28,23 +28,20 @@
#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();
diff --git a/gnuradio-core/src/lib/runtime/gr_simple_flowgraph_detail.cc b/gnuradio-core/src/lib/runtime/gr_simple_flowgraph_detail.cc
index 36dc0bc40..0c9c9b707 100644
--- a/gnuradio-core/src/lib/runtime/gr_simple_flowgraph_detail.cc
+++ b/gnuradio-core/src/lib/runtime/gr_simple_flowgraph_detail.cc
@@ -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);
diff --git a/gnuradio-core/src/lib/runtime/gr_simple_flowgraph_detail.h b/gnuradio-core/src/lib/runtime/gr_simple_flowgraph_detail.h
index d4812b615..2df1575ad 100644
--- a/gnuradio-core/src/lib/runtime/gr_simple_flowgraph_detail.h
+++ b/gnuradio-core/src/lib/runtime/gr_simple_flowgraph_detail.h
@@ -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();
diff --git a/gnuradio-examples/c++/dialtone/dialtone.cc b/gnuradio-examples/c++/dialtone/dialtone.cc
index 08ecccf75..0debb2856 100644
--- a/gnuradio-examples/c++/dialtone/dialtone.cc
+++ b/gnuradio-examples/c++/dialtone/dialtone.cc
@@ -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);
diff --git a/gnuradio-examples/python/audio/dial_tone2.py b/gnuradio-examples/python/audio/dial_tone2.py
index a91c6ff4d..5881f06f7 100755
--- a/gnuradio-examples/python/audio/dial_tone2.py
+++ b/gnuradio-examples/python/audio/dial_tone2.py
@@ -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