diff options
Diffstat (limited to 'gnuradio-core/src/lib/runtime')
5 files changed, 59 insertions, 64 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(); |