From bb5a5a24766e50059ff0756e2877d49c09f3ed9f Mon Sep 17 00:00:00 2001 From: eb Date: Mon, 23 Jun 2008 18:26:50 +0000 Subject: [PATCH] merged refactoring of gr_top_block_impl into abstract base class gr_top_block_impl and concrete class gr_top_block_impl_sts from eb/mp-sched r8447:8660. No change in functionality or behavior. Paves the way for development of multiprocessor aware scheduler. git-svn-id: http://gnuradio.org/svn/gnuradio/trunk@8665 221aa14e-8319-0410-a670-987f0aec2ac5 --- gnuradio-core/src/lib/runtime/Makefile.am | 2 + gnuradio-core/src/lib/runtime/gr_top_block.cc | 3 +- .../src/lib/runtime/gr_top_block_impl.cc | 114 ++------------- .../src/lib/runtime/gr_top_block_impl.h | 38 ++--- .../src/lib/runtime/gr_top_block_impl_sts.cc | 130 ++++++++++++++++++ .../src/lib/runtime/gr_top_block_impl_sts.h | 55 ++++++++ 6 files changed, 225 insertions(+), 117 deletions(-) create mode 100644 gnuradio-core/src/lib/runtime/gr_top_block_impl_sts.cc create mode 100644 gnuradio-core/src/lib/runtime/gr_top_block_impl_sts.h diff --git a/gnuradio-core/src/lib/runtime/Makefile.am b/gnuradio-core/src/lib/runtime/Makefile.am index d84128cb..0463581c 100644 --- a/gnuradio-core/src/lib/runtime/Makefile.am +++ b/gnuradio-core/src/lib/runtime/Makefile.am @@ -55,6 +55,7 @@ libruntime_la_SOURCES = \ gr_sync_interpolator.cc \ gr_top_block.cc \ gr_top_block_impl.cc \ + gr_top_block_impl_sts.cc \ gr_tmp_path.cc \ gr_vmcircbuf.cc \ gr_vmcircbuf_mmap_shm_open.cc \ @@ -102,6 +103,7 @@ grinclude_HEADERS = \ gr_sync_interpolator.h \ gr_top_block.h \ gr_top_block_impl.h \ + gr_top_block_impl_sts.h \ gr_timer.h \ gr_tmp_path.h \ gr_types.h \ diff --git a/gnuradio-core/src/lib/runtime/gr_top_block.cc b/gnuradio-core/src/lib/runtime/gr_top_block.cc index 5cb0ccde..473ea588 100644 --- a/gnuradio-core/src/lib/runtime/gr_top_block.cc +++ b/gnuradio-core/src/lib/runtime/gr_top_block.cc @@ -27,6 +27,7 @@ #include #include #include +#include #include #include @@ -42,7 +43,7 @@ gr_top_block::gr_top_block(const std::string &name) gr_make_io_signature(0,0,0)) { - d_impl = new gr_top_block_impl(this); + d_impl = new gr_top_block_impl_sts(this); } gr_top_block::~gr_top_block() diff --git a/gnuradio-core/src/lib/runtime/gr_top_block_impl.cc b/gnuradio-core/src/lib/runtime/gr_top_block_impl.cc index 359665a7..857e9fa2 100644 --- a/gnuradio-core/src/lib/runtime/gr_top_block_impl.cc +++ b/gnuradio-core/src/lib/runtime/gr_top_block_impl.cc @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2007 Free Software Foundation, Inc. + * Copyright 2007,2008 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -37,55 +37,16 @@ #define GR_TOP_BLOCK_IMPL_DEBUG 0 -static gr_top_block_impl *s_impl = 0; - -/*! - * Make a vector of gr_block from a vector of gr_basic_block - * - * Pass-by-value to avoid problem with possible asynchronous modification - */ -static gr_block_vector_t -make_gr_block_vector(gr_basic_block_vector_t blocks) -{ - gr_block_vector_t result; - for (gr_basic_block_viter_t p = blocks.begin(); p != blocks.end(); p++) { - result.push_back(make_gr_block_sptr(*p)); - } - - return result; -} - -// FIXME: This prevents using more than one gr_top_block instance - -static void -runtime_sigint_handler(int signum) -{ - if (GR_TOP_BLOCK_IMPL_DEBUG){ - char *msg = "SIGINT received, calling stop()\n"; - ::write(1, msg, strlen(msg)); // write is OK to call from signal handler - } - - if (s_impl) - s_impl->stop(); -} - -// ---------------------------------------------------------------- - gr_top_block_impl::gr_top_block_impl(gr_top_block *owner) - : d_running(false), + : d_owner(owner), + d_running(false), d_ffg(), - d_owner(owner), d_lock_count(0) { - if (s_impl) - throw std::logic_error("gr_top_block_impl: multiple simultaneous gr_top_blocks not allowed"); - - s_impl = this; } gr_top_block_impl::~gr_top_block_impl() { - s_impl = 0; // don't call delete we don't own these d_owner = 0; } @@ -109,64 +70,6 @@ gr_top_block_impl::start() start_threads(); } -void -gr_top_block_impl::start_threads() -{ - if (GR_TOP_BLOCK_IMPL_DEBUG) - std::cout << "start_threads: entered" << std::endl; - - d_graphs = d_ffg->partition(); - for (std::vector::iterator p = d_graphs.begin(); - p != d_graphs.end(); p++) { - gr_scheduler_thread *thread = new gr_scheduler_thread(make_gr_block_vector(*p)); - d_threads.push_back(thread); - if (GR_TOP_BLOCK_IMPL_DEBUG) - std::cout << "start_threads: starting " << thread << std::endl; - thread->start(); - } - - d_running = true; -} - -/* - * N.B. as currently implemented, it is possible that this may be - * invoked by the SIGINT handler which is fragile as hell... - */ -void -gr_top_block_impl::stop() -{ - if (GR_TOP_BLOCK_IMPL_DEBUG){ - char *msg = "stop: entered\n"; - ::write(1, msg, strlen(msg)); - } - - for (gr_scheduler_thread_viter_t p = d_threads.begin(); p != d_threads.end(); p++) { - if (*p) - (*p)->stop(); - } -} - -void -gr_top_block_impl::wait() -{ - if (GR_TOP_BLOCK_IMPL_DEBUG) - std::cout << "wait: entered" << std::endl; - - void *dummy_status; // don't ever dereference this - gr_local_sighandler sigint(SIGINT, runtime_sigint_handler); - - for (gr_scheduler_thread_viter_t p = d_threads.begin(); p != d_threads.end(); p++) { - if (GR_TOP_BLOCK_IMPL_DEBUG) - std::cout << "wait: joining thread " << (*p) << std::endl; - (*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 - if (GR_TOP_BLOCK_IMPL_DEBUG) - std::cout << "wait: join returned" << std::endl; - } - - d_threads.clear(); - d_running = false; -} // N.B. lock() and unlock() cannot be called from a flow graph thread or // deadlock will occur when reconfiguration happens @@ -238,3 +141,14 @@ gr_top_block_impl::dump() if (d_ffg) d_ffg->dump(); } + +gr_block_vector_t +gr_top_block_impl::make_gr_block_vector(gr_basic_block_vector_t blocks) +{ + gr_block_vector_t result; + for (gr_basic_block_viter_t p = blocks.begin(); p != blocks.end(); p++) { + result.push_back(make_gr_block_sptr(*p)); + } + + return result; +} diff --git a/gnuradio-core/src/lib/runtime/gr_top_block_impl.h b/gnuradio-core/src/lib/runtime/gr_top_block_impl.h index abdfa996..003afec9 100644 --- a/gnuradio-core/src/lib/runtime/gr_top_block_impl.h +++ b/gnuradio-core/src/lib/runtime/gr_top_block_impl.h @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2007 Free Software Foundation, Inc. + * Copyright 2007,2008 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -26,9 +26,9 @@ #include /*! - *\brief Implementation details of gr_top_block - * + *\brief Abstract implementation details of gr_top_block * \ingroup internal + * * The actual implementation of gr_top_block. Separate class allows * decoupling of changes from dependent classes. * @@ -37,22 +37,22 @@ class gr_top_block_impl { public: gr_top_block_impl(gr_top_block *owner); - ~gr_top_block_impl(); + virtual ~gr_top_block_impl(); // Create and start scheduler threads - void start(); + virtual void start(); // Signal scheduler threads to stop - void stop(); + virtual void stop() = 0; // Wait for scheduler threads to exit - void wait(); + virtual void wait() = 0; // Lock the top block to allow reconfiguration - void lock(); + virtual void lock(); // Unlock the top block at end of reconfiguration - void unlock(); + virtual void unlock(); // Dump the flowgraph to stdout void dump(); @@ -60,19 +60,25 @@ public: // Return true if flowgraph is running bool is_running() const { return d_running; } -private: +protected: + gr_top_block *d_owner; bool d_running; gr_flat_flowgraph_sptr d_ffg; - gr_scheduler_thread_vector_t d_threads; - gr_top_block *d_owner; + + omni_mutex d_reconf; // protects d_lock_count int d_lock_count; - omni_mutex d_reconf; - std::vector d_graphs; + virtual void start_threads() = 0; + virtual void restart(); + +/*! + * Make a vector of gr_block from a vector of gr_basic_block + * + * Pass-by-value to avoid problem with possible asynchronous modification + */ + static gr_block_vector_t make_gr_block_vector(gr_basic_block_vector_t blocks); - void start_threads(); - void restart(); }; #endif /* INCLUDED_GR_TOP_BLOCK_IMPL_H */ diff --git a/gnuradio-core/src/lib/runtime/gr_top_block_impl_sts.cc b/gnuradio-core/src/lib/runtime/gr_top_block_impl_sts.cc new file mode 100644 index 00000000..39289ce5 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_top_block_impl_sts.cc @@ -0,0 +1,130 @@ +/* -*- c++ -*- */ +/* + * Copyright 2007,2008 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#define GR_TOP_BLOCK_IMPL_STS_DEBUG 0 + +static gr_top_block_impl *s_impl = 0; + + +// FIXME: This prevents using more than one gr_top_block instance + +static void +runtime_sigint_handler(int signum) +{ + if (GR_TOP_BLOCK_IMPL_STS_DEBUG){ + char *msg = "SIGINT received, calling stop()\n"; + ::write(1, msg, strlen(msg)); // write is OK to call from signal handler + } + + if (s_impl) + s_impl->stop(); +} + +// ---------------------------------------------------------------- + +gr_top_block_impl_sts::gr_top_block_impl_sts(gr_top_block *owner) + : gr_top_block_impl(owner) +{ + if (s_impl) + throw std::logic_error("gr_top_block_impl_sts: multiple simultaneous gr_top_blocks not allowed"); + + s_impl = this; +} + +gr_top_block_impl_sts::~gr_top_block_impl_sts() +{ + s_impl = 0; // don't call delete we don't own these +} + +void +gr_top_block_impl_sts::start_threads() +{ + if (GR_TOP_BLOCK_IMPL_STS_DEBUG) + std::cout << "start_threads: entered" << std::endl; + + d_graphs = d_ffg->partition(); + for (std::vector::iterator p = d_graphs.begin(); + p != d_graphs.end(); p++) { + gr_scheduler_thread *thread = new gr_scheduler_thread(make_gr_block_vector(*p)); + d_threads.push_back(thread); + if (GR_TOP_BLOCK_IMPL_STS_DEBUG) + std::cout << "start_threads: starting " << thread << std::endl; + thread->start(); + } + + d_running = true; +} + +/* + * N.B. as currently implemented, it is possible that this may be + * invoked by the SIGINT handler which is fragile as hell... + */ +void +gr_top_block_impl_sts::stop() +{ + if (GR_TOP_BLOCK_IMPL_STS_DEBUG){ + char *msg = "stop: entered\n"; + ::write(1, msg, strlen(msg)); + } + + for (gr_scheduler_thread_viter_t p = d_threads.begin(); p != d_threads.end(); p++) { + if (*p) + (*p)->stop(); + } +} + +void +gr_top_block_impl_sts::wait() +{ + if (GR_TOP_BLOCK_IMPL_STS_DEBUG) + std::cout << "wait: entered" << std::endl; + + void *dummy_status; // don't ever dereference this + gr_local_sighandler sigint(SIGINT, runtime_sigint_handler); + + for (gr_scheduler_thread_viter_t p = d_threads.begin(); p != d_threads.end(); p++) { + if (GR_TOP_BLOCK_IMPL_STS_DEBUG) + std::cout << "wait: joining thread " << (*p) << std::endl; + (*p)->join(&dummy_status); // omnithreads will self-delete, so pointer is now dead + (*p) = 0; // FIXME: switch to stl::list and actually remove from container + if (GR_TOP_BLOCK_IMPL_STS_DEBUG) + std::cout << "wait: join returned" << std::endl; + } + + d_threads.clear(); + d_running = false; +} diff --git a/gnuradio-core/src/lib/runtime/gr_top_block_impl_sts.h b/gnuradio-core/src/lib/runtime/gr_top_block_impl_sts.h new file mode 100644 index 00000000..ec2e51cf --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_top_block_impl_sts.h @@ -0,0 +1,55 @@ +/* -*- c++ -*- */ +/* + * Copyright 2007 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_GR_TOP_BLOCK_IMPL_STS_H +#define INCLUDED_GR_TOP_BLOCK_IMPL_STS_H + +#include +#include + +/*! + *\brief Implementation details of gr_top_block + * \ingroup internal + * + * Concrete implementation of gr_top_block using gr_single_threaded_scheduler. + */ +class gr_top_block_impl_sts : public gr_top_block_impl +{ +public: + gr_top_block_impl_sts(gr_top_block *owner); + ~gr_top_block_impl_sts(); + + // Signal scheduler threads to stop + void stop(); + + // Wait for scheduler threads to exit + void wait(); + +private: + + gr_scheduler_thread_vector_t d_threads; + std::vector d_graphs; + + void start_threads(); +}; + +#endif /* INCLUDED_GR_TOP_BLOCK_IMPL_STS_H */ -- 2.30.2