Merged r6171:6186 from jcorgan/fg into trunk.
authorjcorgan <jcorgan@221aa14e-8319-0410-a670-987f0aec2ac5>
Mon, 27 Aug 2007 18:49:11 +0000 (18:49 +0000)
committerjcorgan <jcorgan@221aa14e-8319-0410-a670-987f0aec2ac5>
Mon, 27 Aug 2007 18:49:11 +0000 (18:49 +0000)
Changes hierarchical flow graph API to use gr.top_block instead
of gr.runtime.

See discuss-gnuradio mailing list for explanation of changes.

GRC has not been updated to use the changed API.

git-svn-id: http://gnuradio.org/svn/gnuradio/trunk@6187 221aa14e-8319-0410-a670-987f0aec2ac5

53 files changed:
config/grc_gnuradio_examples.m4
gnuradio-core/src/lib/runtime/Makefile.am
gnuradio-core/src/lib/runtime/gr_hier_block2.cc
gnuradio-core/src/lib/runtime/gr_hier_block2.h
gnuradio-core/src/lib/runtime/gr_hier_block2_detail.cc
gnuradio-core/src/lib/runtime/gr_hier_block2_detail.h
gnuradio-core/src/lib/runtime/gr_runtime.cc [deleted file]
gnuradio-core/src/lib/runtime/gr_runtime.h [deleted file]
gnuradio-core/src/lib/runtime/gr_runtime.i [deleted file]
gnuradio-core/src/lib/runtime/gr_runtime_impl.cc [deleted file]
gnuradio-core/src/lib/runtime/gr_runtime_impl.h [deleted file]
gnuradio-core/src/lib/runtime/gr_runtime_types.h
gnuradio-core/src/lib/runtime/gr_scheduler_thread.cc [new file with mode: 0644]
gnuradio-core/src/lib/runtime/gr_scheduler_thread.h [new file with mode: 0644]
gnuradio-core/src/lib/runtime/gr_top_block.cc [new file with mode: 0644]
gnuradio-core/src/lib/runtime/gr_top_block.h [new file with mode: 0644]
gnuradio-core/src/lib/runtime/gr_top_block.i [new file with mode: 0644]
gnuradio-core/src/lib/runtime/gr_top_block_impl.cc [new file with mode: 0644]
gnuradio-core/src/lib/runtime/gr_top_block_impl.h [new file with mode: 0644]
gnuradio-core/src/lib/runtime/qa_gr_top_block.cc [new file with mode: 0644]
gnuradio-core/src/lib/runtime/qa_gr_top_block.h [new file with mode: 0644]
gnuradio-core/src/lib/runtime/qa_runtime.cc
gnuradio-core/src/lib/runtime/runtime.i
gnuradio-core/src/python/gnuradio/gr/Makefile.am
gnuradio-core/src/python/gnuradio/gr/__init__.py
gnuradio-core/src/python/gnuradio/gr/hier_block2.py
gnuradio-core/src/python/gnuradio/gr/qa_hier_block2.py
gnuradio-core/src/python/gnuradio/gr/qa_runtime.py [deleted file]
gnuradio-core/src/python/gnuradio/gr/top_block.py [new file with mode: 0644]
gnuradio-examples/Makefile.am
gnuradio-examples/c++/Makefile.am
gnuradio-examples/c++/dial_tone/README
gnuradio-examples/c++/dial_tone/dial_tone.cc
gnuradio-examples/c++/dial_tone/dial_tone.h
gnuradio-examples/c++/dial_tone/main.cc
gnuradio-examples/python/hier/audio/dial_tone2.py
gnuradio-examples/python/hier/dect/usrp_dect.py
gnuradio-examples/python/hier/digital/benchmark_loopback.py
gnuradio-examples/python/hier/digital/benchmark_rx.py
gnuradio-examples/python/hier/digital/benchmark_tx.py
gnuradio-examples/python/hier/networking/audio_sink.py
gnuradio-examples/python/hier/networking/audio_source.py
gnuradio-examples/python/hier/networking/dial_tone_sink.py
gnuradio-examples/python/hier/networking/dial_tone_source.py
gnuradio-examples/python/hier/networking/vector_sink.py
gnuradio-examples/python/hier/networking/vector_source.py
gnuradio-examples/python/hier/sounder/usrp_sounder_rx.py
gnuradio-examples/python/hier/sounder/usrp_sounder_tx.py
gnuradio-examples/python/hier/usrp/usrp_siggen.py
gr-pager/src/usrp_flex.py
gr-pager/src/usrp_flex_all.py
gr-pager/src/usrp_flex_band.py
gr-wxgui/src/python/stdgui2.py

index f1ba8f4c50f4efe0f80bcd7e37810f41c504fbac..7b66f747f304aece09120ec8e5c328368fc85fb4 100644 (file)
@@ -22,6 +22,7 @@ AC_DEFUN([GRC_GNURADIO_EXAMPLES],[
 
     AC_CONFIG_FILES([ \
         gnuradio-examples/Makefile \
+       gnuradio-examples/c++/Makefile \
         gnuradio-examples/python/Makefile \
         gnuradio-examples/python/apps/hf_explorer/Makefile \
         gnuradio-examples/python/apps/hf_radio/Makefile \
index 346f23b6a3e19725538c49a8f312b1fab277bd9e..4b51f7f4de4db8bbd0ae8c3d90b6a42fcf8cce8e 100644 (file)
@@ -1,5 +1,5 @@
 #
-# Copyright 2003,2004 Free Software Foundation, Inc.
+# Copyright 2003,2004,2007 Free Software Foundation, Inc.
 # 
 # This file is part of GNU Radio
 # 
@@ -48,12 +48,13 @@ libruntime_la_SOURCES =                     \
        gr_pagesize.cc                          \
        gr_preferences.cc                       \
        gr_realtime.cc                          \
-       gr_runtime.cc                           \
-       gr_runtime_impl.cc                      \
+       gr_scheduler_thread.cc                  \
        gr_single_threaded_scheduler.cc         \
        gr_sync_block.cc                        \
        gr_sync_decimator.cc                    \
        gr_sync_interpolator.cc                 \
+       gr_top_block.cc                         \
+       gr_top_block_impl.cc                    \
        gr_tmp_path.cc                          \
        gr_vmcircbuf.cc                         \
        gr_vmcircbuf_mmap_shm_open.cc           \
@@ -67,6 +68,7 @@ libruntime_qa_la_SOURCES =                    \
        qa_gr_hier_block2.cc                    \
        qa_gr_buffer.cc                         \
        qa_gr_flowgraph.cc                      \
+       qa_gr_top_block.cc                      \
        qa_gr_io_signature.cc                   \
        qa_gr_vmcircbuf.cc                      \
        qa_runtime.cc                           
@@ -91,14 +93,15 @@ grinclude_HEADERS =                                 \
        gr_pagesize.h                           \
        gr_preferences.h                        \
        gr_realtime.h                           \
-       gr_runtime.h                            \
-       gr_runtime_impl.h                       \
        gr_runtime_types.h                      \
+       gr_scheduler_thread.h                   \
        gr_select_handler.h                     \
        gr_single_threaded_scheduler.h          \
        gr_sync_block.h                         \
        gr_sync_decimator.h                     \
        gr_sync_interpolator.h                  \
+       gr_top_block.h                          \
+       gr_top_block_impl.h                     \
        gr_timer.h                              \
        gr_tmp_path.h                           \
        gr_types.h                              \
@@ -114,6 +117,7 @@ noinst_HEADERS =                            \
        qa_gr_hier_block2.h                     \
        qa_gr_buffer.h                          \
        qa_gr_io_signature.h                    \
+       qa_gr_top_block.h                       \
        qa_gr_vmcircbuf.h                       \
        qa_runtime.h                            
 
@@ -130,12 +134,12 @@ swiginclude_HEADERS =                     \
        gr_msg_handler.i                \
        gr_msg_queue.i                  \
        gr_realtime.i                   \
-       gr_runtime.i                    \
        gr_single_threaded_scheduler.i  \
        gr_sync_block.i                 \
        gr_sync_decimator.i             \
        gr_sync_interpolator.i          \
        gr_swig_block_magic.i           \
+       gr_top_block.i                  \
        runtime.i
 
 MOSTLYCLEANFILES = *~ *.loT
index 5b668841234812a45fff0e78e3700845cc6d81aa..890638bae95707f1ac031b62a91f6e72dc1aec30 100644 (file)
@@ -35,7 +35,7 @@ gr_hier_block2_sptr gr_make_hier_block2(const std::string &name,
                                         gr_io_signature_sptr input_signature,
                                         gr_io_signature_sptr output_signature)
 {
-    return gr_hier_block2_sptr(new gr_hier_block2(name, input_signature, output_signature));
+  return gr_hier_block2_sptr(new gr_hier_block2(name, input_signature, output_signature));
 }
 
 gr_hier_block2::gr_hier_block2(const std::string &name,
@@ -48,39 +48,37 @@ gr_hier_block2::gr_hier_block2(const std::string &name,
 
 gr_hier_block2::~gr_hier_block2()
 {
-    delete d_detail;
+  delete d_detail;
 }
 
 void 
 gr_hier_block2::connect(gr_basic_block_sptr src, int src_port, 
                         gr_basic_block_sptr dst, int dst_port)
 {
-    d_detail->connect(src, src_port, dst, dst_port);
+  d_detail->connect(src, src_port, dst, dst_port);
 }
 
 void 
 gr_hier_block2::disconnect(gr_basic_block_sptr src, int src_port, 
                            gr_basic_block_sptr dst, int dst_port)
 {
-    d_detail->disconnect(src, src_port, dst, dst_port);
+  d_detail->disconnect(src, src_port, dst, dst_port);
 }
 
 void
-gr_hier_block2::set_runtime(gr_runtime *runtime)
+gr_hier_block2::lock()
 {
-    if (GR_HIER_BLOCK2_DEBUG)
-      std::cout << "Setting runtime on " << this << " to " << runtime << std::endl;
-    d_detail->set_runtime(runtime);
+  d_detail->lock();
 }
 
 void
-gr_hier_block2::lock()
+gr_hier_block2::unlock()
 {
-    d_detail->lock();
+  d_detail->unlock();
 }
 
 void
-gr_hier_block2::unlock()
+gr_hier_block2::flatten(gr_flat_flowgraph_sptr ffg)
 {
-    d_detail->unlock();
+  d_detail->flatten(ffg);
 }
index 02ce1010627582bbb8eb4e56014fcd8c27e5d916..75223d149a6658b9dc1f4ce3bc86e55b4a12c9ab 100644 (file)
@@ -40,34 +40,32 @@ class gr_hier_block2_detail;
 class gr_hier_block2 : public gr_basic_block
 {
 private:
-    friend class gr_hier_block2_detail;
-    friend class gr_runtime_impl;
-    friend gr_hier_block2_sptr gr_make_hier_block2(const std::string &name,
-                                                   gr_io_signature_sptr input_signature,
-                                                   gr_io_signature_sptr output_signature);
-
-    /*!
-     * \brief Private implementation details of gr_hier_block2
-     */
-    gr_hier_block2_detail *d_detail;
-
-    /* Internal use only */
-    void set_runtime(gr_runtime *runtime);
-
+  friend class gr_hier_block2_detail;
+  friend gr_hier_block2_sptr gr_make_hier_block2(const std::string &name,
+                                                gr_io_signature_sptr input_signature,
+                                                gr_io_signature_sptr output_signature);
+  
+  /*!
+   * \brief Private implementation details of gr_hier_block2
+   */
+  gr_hier_block2_detail *d_detail;
+  
 protected: 
-    gr_hier_block2(const std::string &name,
-                   gr_io_signature_sptr input_signature,
-                   gr_io_signature_sptr output_signature);
-
+  gr_hier_block2(const std::string &name,
+                gr_io_signature_sptr input_signature,
+                gr_io_signature_sptr output_signature);
+  
 public:
-    virtual ~gr_hier_block2();
+  virtual ~gr_hier_block2();
+  
+  void connect(gr_basic_block_sptr src, int src_port, 
+              gr_basic_block_sptr dst, int dst_port);
+  void disconnect(gr_basic_block_sptr src, int src_port,
+                 gr_basic_block_sptr dst, int dst_port);
+  virtual void lock();
+  virtual void unlock();
 
-    void connect(gr_basic_block_sptr src, int src_port, 
-                 gr_basic_block_sptr dst, int dst_port);
-    void disconnect(gr_basic_block_sptr src, int src_port,
-                   gr_basic_block_sptr dst, int dst_port);
-    void lock();
-    void unlock();
+  void flatten(gr_flat_flowgraph_sptr ffg);
 };
 
 #endif /* INCLUDED_GR_HIER_BLOCK2_H */
index 99131afb64acfd72f508857dafecab0e00f6bf0c..15c898c77bc65cdcea4b30daa845bb2d134bccb6 100644 (file)
@@ -25,7 +25,6 @@
 
 #include <gr_hier_block2_detail.h>
 #include <gr_io_signature.h>
-#include <gr_runtime.h>
 #include <stdexcept>
 #include <iostream>
 
@@ -36,8 +35,7 @@ gr_hier_block2_detail::gr_hier_block2_detail(gr_hier_block2 *owner) :
   d_parent_detail(0),
   d_fg(gr_make_flowgraph()),
   d_inputs(owner->input_signature()->max_streams()),
-  d_outputs(owner->output_signature()->max_streams()),
-  d_runtime()
+  d_outputs(owner->output_signature()->max_streams())
 {
 }
 
@@ -263,8 +261,7 @@ gr_hier_block2_detail::lock()
   if (d_parent_detail)
     d_parent_detail->lock();
   else
-    if (d_runtime)
-      d_runtime->lock();
+    d_owner->lock();
 }
 
 void
@@ -276,6 +273,5 @@ gr_hier_block2_detail::unlock()
   if (d_parent_detail)
     d_parent_detail->unlock();
   else
-    if (d_runtime)
-      d_runtime->unlock();
+    d_owner->unlock();
 }
index b315061bec5e5b38c5b544b6783c7b2b9f55e806..ace22ea9aded2e8afe19a118a3576027df12085d 100644 (file)
@@ -40,7 +40,6 @@ private:
     gr_flowgraph_sptr d_fg;
     gr_endpoint_vector_t d_inputs;
     gr_endpoint_vector_t d_outputs;
-    gr_runtime *d_runtime;
 
     // Private implementation methods
     void connect(gr_basic_block_sptr src, int src_port, 
@@ -54,7 +53,6 @@ private:
     void flatten(gr_flat_flowgraph_sptr sfg);
     gr_endpoint resolve_port(int port, bool is_input);
     gr_endpoint resolve_endpoint(const gr_endpoint &endp, bool is_input);
-    void set_runtime(gr_runtime *runtime) { d_runtime = runtime; }
     void lock();
     void unlock();
 
diff --git a/gnuradio-core/src/lib/runtime/gr_runtime.cc b/gnuradio-core/src/lib/runtime/gr_runtime.cc
deleted file mode 100644 (file)
index 6b1419e..0000000
+++ /dev/null
@@ -1,89 +0,0 @@
-/* -*- c++ -*- */
-/*
- * Copyright 2006,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.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <gr_runtime.h>
-#include <gr_runtime_impl.h>
-#include <iostream>
-
-gr_runtime_sptr 
-gr_make_runtime(gr_hier_block2_sptr top_block)
-{
-  return gr_runtime_sptr(new gr_runtime(top_block));
-}
-
-gr_runtime::gr_runtime(gr_hier_block2_sptr top_block)
-{
-  d_impl = new gr_runtime_impl(top_block, this);
-}
-  
-gr_runtime::~gr_runtime()
-{
-  delete d_impl;
-}
-
-void 
-gr_runtime::start()
-{
-  d_impl->start();
-}
-
-void 
-gr_runtime::stop()
-{
-  d_impl->stop();
-}
-
-void 
-gr_runtime::wait()
-{
-  d_impl->wait();
-}
-
-void 
-gr_runtime::run()
-{
-  start();
-  wait();
-}
-
-void
-gr_runtime::restart()
-{
-  d_impl->restart();
-}
-
-void
-gr_runtime::lock()
-{
-  d_impl->lock();
-}
-
-void
-gr_runtime::unlock()
-{
-  d_impl->unlock();
-}
-
diff --git a/gnuradio-core/src/lib/runtime/gr_runtime.h b/gnuradio-core/src/lib/runtime/gr_runtime.h
deleted file mode 100644 (file)
index 1168b3e..0000000
+++ /dev/null
@@ -1,105 +0,0 @@
-/* -*- c++ -*- */
-/*
- * Copyright 2006,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_RUNTIME_H
-#define INCLUDED_GR_RUNTIME_H
-
-#include <gr_runtime_types.h>
-
-class gr_runtime_impl;
-
-gr_runtime_sptr gr_make_runtime(gr_hier_block2_sptr top_block);
-
-/*!
- *\brief Runtime object that controls simple flow graph operation
- *
- * This class is instantiated with a top-level gr_hier_block2. The
- * runtime then flattens the hierarchical block into a gr_simple_flowgraph,
- * and allows control through start(), stop(), wait(), and run().
- * 
- */
-class gr_runtime
-{
-private:
-  gr_runtime(gr_hier_block2_sptr top_block);
-  friend gr_runtime_sptr gr_make_runtime(gr_hier_block2_sptr top_block);
-
-  gr_runtime_impl *d_impl;
-    
-public:
-  ~gr_runtime();
-
-  /*!
-   * Start the flow graph.  Creates an undetached scheduler thread for
-   * each flow graph partition. Returns to caller once created.
-   */
-  void start();
-  
-  /*!
-   * Stop a running flow graph.  Tells each created scheduler thread
-   * to exit, then returns to caller.
-   */
-  void stop();
-
-  /*!
-   * Wait for a stopped flow graph to complete.  Joins each completed
-   * thread.
-   */
-  void wait();
-
-  /*!
-   * Calls start(), then wait().  Used to run a flow graph that will stop
-   * on its own, or to run a flow graph indefinitely until SIGTERM is
-   * received().
-   */
-  void run();
-
-  /*!
-   * Restart a running flow graph, after topology changes have
-   * been made to its top_block (or children). Causes each created 
-   * scheduler thread to end, recalculates the flow graph, and 
-   * recreates new threads (possibly a different number from before.)
-   */
-  void restart();
-
-  /*!
-   * Lock a flow graph in preparation for reconfiguration.  When an equal
-   * number of calls to lock() and unlock() have occurred, the flow graph
-   * will be restarted automatically.
-   *
-   * N.B. lock() and unlock() cannot be called from a flow graph thread or
-   * deadlock will occur when reconfiguration happens.
-   */
-  void lock();
-
-  /*!
-   * Lock a flow graph in preparation for reconfiguration.  When an equal
-   * number of calls to lock() and unlock() have occurred, the flow graph
-   * will be restarted automatically.
-   *
-   * N.B. lock() and unlock() cannot be called from a flow graph thread or
-   * deadlock will occur when reconfiguration happens.
-   */
-  void unlock();
-};
-
-#endif /* INCLUDED_GR_RUNTIME_H */
diff --git a/gnuradio-core/src/lib/runtime/gr_runtime.i b/gnuradio-core/src/lib/runtime/gr_runtime.i
deleted file mode 100644 (file)
index d750553..0000000
+++ /dev/null
@@ -1,82 +0,0 @@
-/* -*- c++ -*- */
-/*
- * Copyright 2004,2006,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.
- */
-
-class gr_runtime;
-typedef boost::shared_ptr<gr_runtime> gr_runtime_sptr;
-%template(gr_runtime_sptr) boost::shared_ptr<gr_runtime>;
-
-gr_runtime_sptr gr_make_runtime(gr_hier_block2_sptr top_block);
-
-class gr_runtime
-{
-protected:
-    gr_runtime(gr_hier_block2_sptr top_block);
-
-public:
-    void run() throw (std::runtime_error);
-    void start() throw (std::runtime_error);
-    void stop() throw (std::runtime_error);
-    void wait() throw (std::runtime_error);
-    void restart() throw (std::runtime_error);
-};
-
-%{
-class ensure_py_gil_state2 {
-    PyGILState_STATE   d_gstate;
-public:
-  ensure_py_gil_state2()  { d_gstate = PyGILState_Ensure(); }
-  ~ensure_py_gil_state2() { PyGILState_Release(d_gstate); }
-};
-%}
-
-%inline %{
-void runtime_run_unlocked(gr_runtime_sptr r) throw (std::runtime_error) 
-{
-    ensure_py_gil_state2 _lock;
-    r->run();
-}
-
-void runtime_start_unlocked(gr_runtime_sptr r) throw (std::runtime_error) 
-{
-    ensure_py_gil_state2 _lock;
-    r->start();
-}
-
-void runtime_stop_unlocked(gr_runtime_sptr r) throw (std::runtime_error) 
-{
-    ensure_py_gil_state2 _lock;
-    r->stop();
-}
-
-void runtime_wait_unlocked(gr_runtime_sptr r) throw (std::runtime_error) 
-{
-    ensure_py_gil_state2 _lock;
-    r->wait();
-}
-
-void runtime_restart_unlocked(gr_runtime_sptr r) throw (std::runtime_error) 
-{
-    ensure_py_gil_state2 _lock;
-    r->restart();
-}
-
-%}
diff --git a/gnuradio-core/src/lib/runtime/gr_runtime_impl.cc b/gnuradio-core/src/lib/runtime/gr_runtime_impl.cc
deleted file mode 100644 (file)
index 30a39f1..0000000
+++ /dev/null
@@ -1,253 +0,0 @@
-/* -*- c++ -*- */
-/*
- * Copyright 2006,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.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <gr_runtime.h>
-#include <gr_runtime_impl.h>
-#include <gr_flat_flowgraph.h>
-#include <gr_hier_block2.h>
-#include <gr_hier_block2_detail.h>
-#include <gr_local_sighandler.h>
-
-#ifdef HAVE_SIGNAL_H
-#include <signal.h>
-#endif
-
-#include <stdexcept>
-#include <iostream>
-
-#define GR_RUNTIME_IMPL_DEBUG 0
-
-static gr_runtime_impl *s_runtime = 0;
-
-// Make a vector of gr_block from a vector of gr_basic_block
-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_runtime instance
-void 
-runtime_sigint_handler(int signum)
-{
-  if (GR_RUNTIME_IMPL_DEBUG)
-    std::cout << "SIGINT received, calling stop() on all threads" << std::endl;
-
-  if (s_runtime)
-    s_runtime->stop();
-}
-
-gr_runtime_impl::gr_runtime_impl(gr_hier_block2_sptr top_block, gr_runtime *owner) 
-  : d_running(false),
-    d_top_block(top_block),
-    d_ffg(gr_make_flat_flowgraph()),
-    d_owner(owner)
-{
-  s_runtime = this;
-  top_block->set_runtime(d_owner);
-}
-
-gr_runtime_impl::~gr_runtime_impl()
-{
-  s_runtime = 0; // don't call delete we don't own these
-  d_owner = 0;
-}
-
-void
-gr_runtime_impl::start()
-{
-  if (GR_RUNTIME_IMPL_DEBUG)
-    std::cout << "start: entered" << std::endl;
-
-  if (d_running)
-    throw std::runtime_error("already running");
-
-  // Create new simple flow graph by flattening hierarchical block
-  d_ffg->clear();
-  d_top_block->d_detail->flatten(d_ffg);
-
-  // Validate new simple flow graph and wire it up
-  d_ffg->validate();
-  d_ffg->setup_connections();
-
-  // Execute scheduler threads
-  start_threads();
-}
-
-void
-gr_runtime_impl::start_threads()
-{
-  if (GR_RUNTIME_IMPL_DEBUG)
-    std::cout << "start_threads: entered" << std::endl;
-
-  d_graphs = d_ffg->partition();
-  for (std::vector<gr_basic_block_vector_t>::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_RUNTIME_IMPL_DEBUG)
-      std::cout << "start_threads: starting " << thread << std::endl;
-    thread->start();
-  }
-
-  d_running = true;
-}
-
-void
-gr_runtime_impl::stop()
-{
-  if (GR_RUNTIME_IMPL_DEBUG)
-    std::cout << "stop: entered" << std::endl;
-
-  for (gr_scheduler_thread_viter_t p = d_threads.begin(); p != d_threads.end(); p++) {
-    if (GR_RUNTIME_IMPL_DEBUG)
-      std::cout << "stop: stopping thread " << (*p) << std::endl;
-    (*p)->stop();
-  }
-
-  d_running = false;
-}
-
-void
-gr_runtime_impl::wait()
-{
-  if (GR_RUNTIME_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_RUNTIME_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_RUNTIME_IMPL_DEBUG)
-      std::cout << "wait: join returned" << std::endl;
-  }
-
-  d_threads.clear();
-}
-
-
-// N.B. lock() and unlock() cannot be called from a flow graph thread or
-// deadlock will occur when reconfiguration happens
-void
-gr_runtime_impl::lock()
-{
-  omni_mutex_lock lock(d_reconf);
-  d_lock_count++;
-  if (GR_RUNTIME_IMPL_DEBUG)
-    std::cout << "runtime: locked, count = " << d_lock_count <<  std::endl;
-}
-
-void
-gr_runtime_impl::unlock()
-{
-  omni_mutex_lock lock(d_reconf);
-  if (d_lock_count == 0)
-    throw std::runtime_error("unpaired unlock() call");
-
-  d_lock_count--;
-  if (GR_RUNTIME_IMPL_DEBUG)
-    std::cout << "runtime: unlocked, count = " << d_lock_count << std::endl;
-
-  if (d_lock_count == 0)
-    restart();
-}
-
-void
-gr_runtime_impl::restart()
-{
-  if (GR_RUNTIME_IMPL_DEBUG)
-    std::cout << "restart: entered" << std::endl;
-
-  if (!d_running)
-    throw std::runtime_error("not running");
-
-  // Stop scheduler threads and wait for completion
-  stop();
-  wait();
-  if (GR_RUNTIME_IMPL_DEBUG)
-    std::cout << "restart: threads stopped" << std::endl;
-
-  // Create new simple flow graph 
-  gr_flat_flowgraph_sptr new_ffg = gr_make_flat_flowgraph();
-  d_top_block->d_detail->flatten(new_ffg);
-  new_ffg->validate();
-  new_ffg->merge_connections(d_ffg);
-
-  if (GR_RUNTIME_IMPL_DEBUG)
-    std::cout << "restart: replacing old flow graph with new" << std::endl;
-  d_ffg = new_ffg;
-
-  start_threads();
-}
-
-gr_scheduler_thread::gr_scheduler_thread(gr_block_vector_t graph) :
-  omni_thread(NULL, PRIORITY_NORMAL),
-  d_sts(gr_make_single_threaded_scheduler(graph))
-{
-}
-
-gr_scheduler_thread::~gr_scheduler_thread()
-{
-}
-
-void gr_scheduler_thread::start()
-{
-  start_undetached();
-}
-
-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
-#ifdef HAVE_SIGPROCMASK
-  sigset_t old_set;
-  sigset_t new_set;
-  sigemptyset(&new_set);
-  sigaddset(&new_set, SIGINT);
-  sigprocmask(SIG_BLOCK, &new_set, &old_set);
-#endif
-  // Run the single-threaded scheduler
-  d_sts->run();
-  return 0;
-}
-
-void
-gr_scheduler_thread::stop()
-{
-  d_sts->stop();
-}
diff --git a/gnuradio-core/src/lib/runtime/gr_runtime_impl.h b/gnuradio-core/src/lib/runtime/gr_runtime_impl.h
deleted file mode 100644 (file)
index f623001..0000000
+++ /dev/null
@@ -1,95 +0,0 @@
-/* -*- c++ -*- */
-/*
- * Copyright 2006,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_RUNTIME_IMPL_H
-#define INCLUDED_GR_RUNTIME_IMPL_H
-
-#include <gr_runtime_types.h>
-#include <gr_block.h>
-#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 std::vector<gr_scheduler_thread *> gr_scheduler_thread_vector_t;
-typedef gr_scheduler_thread_vector_t::iterator gr_scheduler_thread_viter_t;
-
-/*!
- *\brief A single thread of execution for the scheduler
- *
- * This class implements a single thread that runs undetached, and
- * invokes the single-threaded block scheduler.  The runtime makes
- * one of these for each distinct partition of a flowgraph and runs
- * them in parallel.
- *
- */
-class gr_scheduler_thread : public omni_thread
-{
-private:
-  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();
-};
-
-/*!
- *\brief Implementation details of gr_runtime
- *
- * The actual implementation of gr_runtime. Separate class allows
- * decoupling of changes from dependent classes.
- *
- */
-class gr_runtime_impl
-{
-private:
-  gr_runtime_impl(gr_hier_block2_sptr top_block, gr_runtime *owner);
-  friend void runtime_sigint_handler(int signum);
-  friend class gr_runtime;
-    
-  bool                           d_running;
-  gr_hier_block2_sptr            d_top_block;
-  gr_flat_flowgraph_sptr         d_ffg;
-  std::vector<gr_basic_block_vector_t> d_graphs;
-  gr_scheduler_thread_vector_t   d_threads;
-  gr_runtime                    *d_owner;
-  int                            d_lock_count;
-  omni_mutex                     d_reconf;
-
-  void start();
-  void start_threads();
-  void stop();
-  void wait();
-  void restart();
-  void lock();
-  void unlock();
-
-public:
-  ~gr_runtime_impl();
-
-};
-
-#endif /* INCLUDED_GR_RUNTIME_IMPL_H */
index 8af663cdfc271805ca594b62108a31f54cb80bee..74d2614a8360c7c41ebe80eee6eb89ba053777e5 100644 (file)
@@ -38,7 +38,8 @@ class gr_buffer;
 class gr_buffer_reader;
 class gr_flowgraph;
 class gr_flat_flowgraph;
-class gr_runtime;
+class gr_top_block;
+class gr_top_block_detail;
 
 typedef boost::shared_ptr<gr_basic_block>       gr_basic_block_sptr;
 typedef boost::shared_ptr<gr_block>             gr_block_sptr;
@@ -47,8 +48,8 @@ typedef boost::shared_ptr<gr_hier_block2>     gr_hier_block2_sptr;
 typedef boost::shared_ptr<gr_io_signature>      gr_io_signature_sptr;
 typedef boost::shared_ptr<gr_buffer>           gr_buffer_sptr;
 typedef boost::shared_ptr<gr_buffer_reader>    gr_buffer_reader_sptr;
-typedef boost::shared_ptr<gr_runtime>          gr_runtime_sptr;
 typedef boost::shared_ptr<gr_flowgraph>         gr_flowgraph_sptr;
 typedef boost::shared_ptr<gr_flat_flowgraph>    gr_flat_flowgraph_sptr;
+typedef boost::shared_ptr<gr_top_block>         gr_top_block_sptr;
 
 #endif /* INCLUDED_GR_RUNTIME_TYPES_H */
diff --git a/gnuradio-core/src/lib/runtime/gr_scheduler_thread.cc b/gnuradio-core/src/lib/runtime/gr_scheduler_thread.cc
new file mode 100644 (file)
index 0000000..9cce5ea
--- /dev/null
@@ -0,0 +1,75 @@
+/* -*- 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gr_scheduler_thread.h>
+#include <iostream>
+
+#ifdef HAVE_SIGNAL_H
+#include <signal.h>
+#endif
+
+#define GR_SCHEDULER_THREAD_DEBUG 0
+
+gr_scheduler_thread::gr_scheduler_thread(gr_block_vector_t graph) :
+  omni_thread(NULL, PRIORITY_NORMAL),
+  d_sts(gr_make_single_threaded_scheduler(graph))
+{
+}
+
+gr_scheduler_thread::~gr_scheduler_thread()
+{
+}
+
+void gr_scheduler_thread::start()
+{
+  start_undetached();
+}
+
+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
+#ifdef HAVE_SIGPROCMASK
+  sigset_t old_set;
+  sigset_t new_set;
+  sigemptyset(&new_set);
+  sigaddset(&new_set, SIGINT);
+  sigprocmask(SIG_BLOCK, &new_set, &old_set);
+#endif
+  // Run the single-threaded scheduler
+  d_sts->run();
+  return 0;
+}
+
+void
+gr_scheduler_thread::stop()
+{
+  if (GR_SCHEDULER_THREAD_DEBUG)
+    std::cout << "gr_scheduler_thread::stop()" << std::endl;
+  d_sts->stop();
+}
diff --git a/gnuradio-core/src/lib/runtime/gr_scheduler_thread.h b/gnuradio-core/src/lib/runtime/gr_scheduler_thread.h
new file mode 100644 (file)
index 0000000..c989f79
--- /dev/null
@@ -0,0 +1,58 @@
+/* -*- 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_SCHEDULER_THREAD_H
+#define INCLUDED_GR_SCHEDULER_THREAD_H
+
+#include <omnithread.h>
+#include <gr_single_threaded_scheduler.h>
+#include <gr_block.h>
+
+// omnithread calls delete on itself after thread exits, so can't use shared ptr
+class gr_scheduler_thread;
+typedef std::vector<gr_scheduler_thread *> gr_scheduler_thread_vector_t;
+typedef gr_scheduler_thread_vector_t::iterator gr_scheduler_thread_viter_t;
+
+/*!
+ *\brief A single thread of execution for the scheduler
+ *
+ * This class implements a single thread that runs undetached, and
+ * invokes the single-threaded block scheduler.  The runtime makes
+ * one of these for each distinct partition of a flowgraph and runs
+ * them in parallel.
+ *
+ */
+class gr_scheduler_thread : public omni_thread
+{
+private:
+  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();
+};
+
+#endif /* INCLUDED_GR_SCHEDULER_THREAD_H */
diff --git a/gnuradio-core/src/lib/runtime/gr_top_block.cc b/gnuradio-core/src/lib/runtime/gr_top_block.cc
new file mode 100644 (file)
index 0000000..407df8b
--- /dev/null
@@ -0,0 +1,87 @@
+/* -*- 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gr_top_block.h>
+#include <gr_top_block_impl.h>
+#include <gr_io_signature.h>
+#include <iostream>
+
+gr_top_block_sptr 
+gr_make_top_block(const std::string &name)
+{
+  return gr_top_block_sptr(new gr_top_block(name));
+}
+
+gr_top_block::gr_top_block(const std::string &name)
+  : gr_hier_block2(name, 
+                  gr_make_io_signature(0,0,0), 
+                  gr_make_io_signature(0,0,0))
+  
+{
+  d_impl = new gr_top_block_impl(this);
+}
+  
+gr_top_block::~gr_top_block()
+{
+  delete d_impl;
+}
+
+void 
+gr_top_block::start()
+{
+  d_impl->start();
+}
+
+void 
+gr_top_block::stop()
+{
+  d_impl->stop();
+}
+
+void 
+gr_top_block::wait()
+{
+  d_impl->wait();
+}
+
+void 
+gr_top_block::run()
+{
+  start();
+  wait();
+}
+
+void
+gr_top_block::lock()
+{
+  d_impl->lock();
+}
+
+void
+gr_top_block::unlock()
+{
+  d_impl->unlock();
+}
diff --git a/gnuradio-core/src/lib/runtime/gr_top_block.h b/gnuradio-core/src/lib/runtime/gr_top_block.h
new file mode 100644 (file)
index 0000000..16fd970
--- /dev/null
@@ -0,0 +1,95 @@
+/* -*- 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_H
+#define INCLUDED_GR_TOP_BLOCK_H
+
+#include <gr_hier_block2.h>
+
+class gr_top_block_impl;
+
+gr_top_block_sptr gr_make_top_block(const std::string &name);
+
+/*!
+ *\brief Top-level hierarchical block representing a flowgraph
+ *
+ */
+class gr_top_block : public gr_hier_block2
+{
+private:
+  friend gr_top_block_sptr gr_make_top_block(const std::string &name);
+
+  gr_top_block_impl *d_impl;
+
+protected:
+  gr_top_block(const std::string &name);
+    
+public:
+  ~gr_top_block();
+
+  /*!
+   * Start the enclosed flowgraph.  Creates an undetached scheduler thread for
+   * each flow graph partition. Returns to caller once created.
+   */
+  void start();
+  
+  /*!
+   * Stop the running flowgraph.  Tells each created scheduler thread
+   * to exit, then returns to caller.
+   */
+  void stop();
+
+  /*!
+   * Wait for a stopped flowgraph to complete.  Joins each completed
+   * thread.
+   */
+  void wait();
+
+  /*!
+   * Calls start(), then wait().  Used to run a flowgraph that will stop
+   * on its own, or to run a flowgraph indefinitely until SIGKILL is
+   * received().
+   */
+  void run();
+
+  /*!
+   * Lock a flowgraph in preparation for reconfiguration.  When an equal
+   * number of calls to lock() and unlock() have occurred, the flowgraph
+   * will be restarted automatically.
+   *
+   * N.B. lock() and unlock() cannot be called from a flowgraph thread or
+   * deadlock will occur when reconfiguration happens.
+   */
+  virtual void lock();
+
+  /*!
+   * Lock a flowgraph in preparation for reconfiguration.  When an equal
+   * number of calls to lock() and unlock() have occurred, the flowgraph
+   * will be restarted automatically.
+   *
+   * N.B. lock() and unlock() cannot be called from a flowgraph thread or
+   * deadlock will occur when reconfiguration happens.
+   */
+  virtual void unlock();
+};
+
+#endif /* INCLUDED_GR_TOP_BLOCK_H */
diff --git a/gnuradio-core/src/lib/runtime/gr_top_block.i b/gnuradio-core/src/lib/runtime/gr_top_block.i
new file mode 100644 (file)
index 0000000..d310f2a
--- /dev/null
@@ -0,0 +1,71 @@
+/* -*- 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.
+ */
+
+%include <gr_top_block.i>
+
+class gr_top_block;
+typedef boost::shared_ptr<gr_top_block> gr_top_block_sptr;
+%template(gr_top_block_sptr) boost::shared_ptr<gr_top_block>;
+
+// Hack to have a Python shim implementation of gr.top_block
+// that instantiates one of these and passes through calls
+%rename(top_block_swig) gr_make_top_block;
+gr_top_block_sptr gr_make_top_block(const std::string name);
+
+class gr_top_block : public gr_hier_block2
+{
+private:
+  gr_top_block(const std::string &name);
+    
+public:
+  ~gr_top_block();
+
+  void start();
+  void stop();
+  void wait();
+  void run();
+  void lock();
+  void unlock();
+};
+
+%{
+class ensure_py_gil_state2 {
+    PyGILState_STATE   d_gstate;
+public:
+  ensure_py_gil_state2()  { d_gstate = PyGILState_Ensure(); }
+  ~ensure_py_gil_state2() { PyGILState_Release(d_gstate); }
+};
+%}
+
+%inline %{
+void top_block_run_unlocked(gr_top_block_sptr r) throw (std::runtime_error) 
+{
+    ensure_py_gil_state2 _lock;
+    r->run();
+}
+
+void top_block_wait_unlocked(gr_top_block_sptr r) throw (std::runtime_error) 
+{
+    ensure_py_gil_state2 _lock;
+    r->wait();
+}
+%}
diff --git a/gnuradio-core/src/lib/runtime/gr_top_block_impl.cc b/gnuradio-core/src/lib/runtime/gr_top_block_impl.cc
new file mode 100644 (file)
index 0000000..f0b67dd
--- /dev/null
@@ -0,0 +1,210 @@
+/* -*- 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gr_top_block.h>
+#include <gr_top_block_impl.h>
+#include <gr_flat_flowgraph.h>
+#include <gr_scheduler_thread.h>
+#include <gr_local_sighandler.h>
+
+#include <stdexcept>
+#include <iostream>
+
+#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
+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)
+    std::cout << "SIGINT received, calling stop()" << std::endl;
+
+  if (s_impl)
+    s_impl->stop();
+}
+
+gr_top_block_impl::gr_top_block_impl(gr_top_block *owner) 
+  : d_running(false),
+    d_ffg(gr_make_flat_flowgraph()),
+    d_owner(owner),
+    d_lock_count(0)
+{
+  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;
+}
+
+void
+gr_top_block_impl::start()
+{
+  if (GR_TOP_BLOCK_IMPL_DEBUG)
+    std::cout << "start: entered" << std::endl;
+
+  if (d_running)
+    throw std::runtime_error("already running");
+
+  // Create new flat flow graph by flattening hierarchy
+  d_ffg->clear();
+  d_owner->flatten(d_ffg);
+
+  // Validate new simple flow graph and wire it up
+  d_ffg->validate();
+  d_ffg->setup_connections();
+
+  // Execute scheduler threads
+  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<gr_basic_block_vector_t>::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;
+}
+
+void
+gr_top_block_impl::stop()
+{
+  if (GR_TOP_BLOCK_IMPL_DEBUG)
+    std::cout << "stop: entered" << std::endl;
+
+  for (gr_scheduler_thread_viter_t p = d_threads.begin(); p != d_threads.end(); p++) {
+    if (GR_TOP_BLOCK_IMPL_DEBUG)
+      std::cout << "stop: stopping thread " << (*p) << std::endl;
+    (*p)->stop();
+  }
+
+  d_running = false;
+}
+
+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();
+}
+
+// N.B. lock() and unlock() cannot be called from a flow graph thread or
+// deadlock will occur when reconfiguration happens
+void
+gr_top_block_impl::lock()
+{
+  omni_mutex_lock lock(d_reconf);
+  d_lock_count++;
+  if (GR_TOP_BLOCK_IMPL_DEBUG)
+    std::cout << "runtime: locked, count = " << d_lock_count <<  std::endl;
+}
+
+void
+gr_top_block_impl::unlock()
+{
+  omni_mutex_lock lock(d_reconf);
+  if (d_lock_count == 0)
+    throw std::runtime_error("unpaired unlock() call");
+
+  d_lock_count--;
+  if (GR_TOP_BLOCK_IMPL_DEBUG)
+    std::cout << "unlock: unlocked, count = " << d_lock_count << std::endl;
+
+  if (d_lock_count == 0) {
+    if (GR_TOP_BLOCK_IMPL_DEBUG)
+      std::cout << "unlock: restarting flowgraph" << std::endl;
+    restart();
+  }
+}
+
+void
+gr_top_block_impl::restart()
+{
+  if (GR_TOP_BLOCK_IMPL_DEBUG)
+    std::cout << "restart: entered" << std::endl;
+
+  if (!d_running)
+    throw std::runtime_error("not running");
+
+  // Stop scheduler threads and wait for completion
+  stop();
+  wait();
+  if (GR_TOP_BLOCK_IMPL_DEBUG)
+    std::cout << "restart: threads stopped" << std::endl;
+
+  // Create new simple flow graph 
+  gr_flat_flowgraph_sptr new_ffg = gr_make_flat_flowgraph();
+  d_owner->flatten(new_ffg);
+  new_ffg->validate();
+  new_ffg->merge_connections(d_ffg);
+
+  if (GR_TOP_BLOCK_IMPL_DEBUG)
+    std::cout << "restart: replacing old flow graph with new" << std::endl;
+  d_ffg = new_ffg;
+
+  start_threads();
+}
diff --git a/gnuradio-core/src/lib/runtime/gr_top_block_impl.h b/gnuradio-core/src/lib/runtime/gr_top_block_impl.h
new file mode 100644 (file)
index 0000000..8052ce4
--- /dev/null
@@ -0,0 +1,71 @@
+/* -*- 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_H
+#define INCLUDED_GR_TOP_BLOCK_IMPL_H
+
+#include <gr_scheduler_thread.h>
+
+/*!
+ *\brief Implementation details of gr_top_block
+ *
+ * The actual implementation of gr_top_block. Separate class allows
+ * decoupling of changes from dependent classes.
+ *
+ */
+class gr_top_block_impl
+{
+public:
+  gr_top_block_impl(gr_top_block *owner);
+  ~gr_top_block_impl();
+
+  // Create and start scheduler threads
+  void start();
+
+  // Signal scheduler threads to stop
+  void stop();
+
+  // Wait for scheduler threads to exit
+  void wait();
+
+  // Lock the top block to allow reconfiguration
+  void lock();
+
+  // Unlock the top block at end of reconfiguration
+  void unlock();
+
+private:
+    
+  bool                           d_running;
+  gr_flat_flowgraph_sptr         d_ffg;
+  gr_scheduler_thread_vector_t   d_threads;
+  gr_top_block                  *d_owner;
+  int                            d_lock_count;
+  omni_mutex                     d_reconf;
+
+  std::vector<gr_basic_block_vector_t> d_graphs;
+
+  void start_threads();
+  void restart();
+};
+
+#endif /* INCLUDED_GR_TOP_BLOCK_IMPL_H */
diff --git a/gnuradio-core/src/lib/runtime/qa_gr_top_block.cc b/gnuradio-core/src/lib/runtime/qa_gr_top_block.cc
new file mode 100644 (file)
index 0000000..3322b6a
--- /dev/null
@@ -0,0 +1,110 @@
+/* -*- 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <qa_gr_top_block.h>
+#include <gr_top_block.h>
+#include <gr_head.h>
+#include <gr_null_source.h>
+#include <gr_null_sink.h>
+
+void qa_gr_top_block::t0()
+{
+  gr_top_block_sptr tb = gr_make_top_block("top");
+
+  CPPUNIT_ASSERT(tb);
+}
+
+void qa_gr_top_block::t1_run()
+{
+  gr_top_block_sptr tb = gr_make_top_block("top");
+
+  gr_block_sptr src = gr_make_null_source(sizeof(int));
+  gr_block_sptr head = gr_make_head(sizeof(int), 1);
+  gr_block_sptr dst = gr_make_null_sink(sizeof(int));
+
+  tb->connect(src, 0, head, 0);
+  tb->connect(head, 0, dst, 0);
+  tb->run();
+}
+
+void qa_gr_top_block::t2_start_stop_wait()
+{
+  gr_top_block_sptr tb = gr_make_top_block("top");
+
+  gr_block_sptr src = gr_make_null_source(sizeof(int));
+  gr_block_sptr head = gr_make_head(sizeof(int), 1000000);
+  gr_block_sptr dst = gr_make_null_sink(sizeof(int));
+
+  tb->connect(src, 0, head, 0);
+  tb->connect(head, 0, dst, 0);
+
+  tb->start();
+  tb->stop();
+  tb->wait();
+}
+
+void qa_gr_top_block::t3_lock_unlock()
+{
+  gr_top_block_sptr tb = gr_make_top_block("top");
+
+  gr_block_sptr src = gr_make_null_source(sizeof(int));
+  gr_block_sptr head = gr_make_head(sizeof(int), 1000000);
+  gr_block_sptr dst = gr_make_null_sink(sizeof(int));
+
+  tb->connect(src, 0, head, 0);
+  tb->connect(head, 0, dst, 0);
+
+  tb->start();
+
+  tb->lock();
+  tb->unlock();
+
+  tb->stop();
+  tb->wait();
+}
+
+void qa_gr_top_block::t4_reconfigure()
+{
+  gr_top_block_sptr tb = gr_make_top_block("top");
+
+  gr_block_sptr src = gr_make_null_source(sizeof(int));
+  gr_block_sptr head = gr_make_head(sizeof(int), 1);
+  gr_block_sptr dst = gr_make_null_sink(sizeof(int));
+
+  // Start infinite flowgraph
+  tb->connect(src, 0, dst, 0);
+  tb->start();
+
+  // Reconfigure with gr_head in the middle
+  tb->lock();
+  tb->disconnect(src, 0, dst, 0);
+  tb->connect(src, 0, head, 0);
+  tb->connect(head, 0, dst, 0);
+  tb->unlock();
+
+  // Wait for flowgraph to end on its own
+  tb->wait();
+}
diff --git a/gnuradio-core/src/lib/runtime/qa_gr_top_block.h b/gnuradio-core/src/lib/runtime/qa_gr_top_block.h
new file mode 100644 (file)
index 0000000..9a24345
--- /dev/null
@@ -0,0 +1,51 @@
+/* -*- 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_QA_GR_TOP_BLOCK_H
+#define INCLUDED_QA_GR_TOP_BLOCK_H
+
+#include <cppunit/extensions/HelperMacros.h>
+#include <cppunit/TestCase.h>
+#include <stdexcept>
+
+class qa_gr_top_block : public CppUnit::TestCase 
+{
+  CPPUNIT_TEST_SUITE(qa_gr_top_block);
+  
+  CPPUNIT_TEST(t0);
+  CPPUNIT_TEST(t1_run);
+  CPPUNIT_TEST(t2_start_stop_wait);
+  CPPUNIT_TEST(t3_lock_unlock);
+  // CPPUNIT_TEST(t4_reconfigure);  triggers 'join never returns' bug
+
+  CPPUNIT_TEST_SUITE_END();
+
+private:
+
+  void t0();
+  void t1_run();
+  void t2_start_stop_wait();
+  void t3_lock_unlock();
+  void t4_reconfigure();
+};
+
+#endif /* INCLUDED_QA_GR_TOP_BLOCK_H */
index 5c00a4fbe1234f4ac4ed56590f61f74c0f7b2aa7..ba0f14b93c0922b187d1e014e78bbb16e432bd19 100644 (file)
@@ -34,6 +34,7 @@
 #include <qa_gr_io_signature.h>
 #include <qa_gr_block.h>
 #include <qa_gr_flowgraph.h>
+#include <qa_gr_top_block.h>
 #include <qa_gr_hier_block2.h>
 #include <qa_gr_buffer.h>
 
@@ -46,6 +47,7 @@ qa_runtime::suite ()
   s->addTest (qa_gr_io_signature::suite ());
   s->addTest (qa_gr_block::suite ());
   s->addTest (qa_gr_flowgraph::suite ());
+  s->addTest (qa_gr_top_block::suite ());
   s->addTest (qa_gr_hier_block2::suite ());
   s->addTest (qa_gr_buffer::suite ());
   
index d162cff9b90deca872a82ef8629a367917c8af7b..20cf68a030212b83b70fd366d5a4535909d2d9b1 100644 (file)
@@ -27,7 +27,6 @@
 #include <gr_block.h>
 #include <gr_block_detail.h>
 #include <gr_hier_block2.h>
-#include <gr_runtime.h>
 #include <gr_single_threaded_scheduler.h>
 #include <gr_message.h>
 #include <gr_msg_handler.h>
@@ -38,6 +37,7 @@
 #include <gr_sync_block.h>
 #include <gr_sync_decimator.h>
 #include <gr_sync_interpolator.h>
+#include <gr_top_block.h>
 %}
 
 %include <gr_io_signature.i>
@@ -54,7 +54,7 @@
 %include <gr_dispatcher.i>
 %include <gr_error_handler.i>
 %include <gr_realtime.i>
-%include <gr_runtime.i>
 %include <gr_sync_block.i>
 %include <gr_sync_decimator.i>
 %include <gr_sync_interpolator.i>
+%include <gr_top_block.i>
index c9c946c2b83241720c98f3715d7a58fece410ab3..77cc53e3f6fa701c63752d225f953f0b026b7ca0 100644 (file)
@@ -41,7 +41,8 @@ grgrpython_PYTHON =           \
        hier_block.py           \
        hier_block2.py          \
        prefs.py                \
-       scheduler.py            
+       scheduler.py            \
+       top_block.py
 
 noinst_PYTHON =                        \
        benchmark_filters.py            \
index 8da93ec57643ffa73cc9eefdb9222a9ff7bb79aa..69f745fbf2494a1c3b4f75904577c0d1f8898fe7 100644 (file)
@@ -30,6 +30,7 @@ from flow_graph import *
 from exceptions import *
 from hier_block import *
 from hier_block2 import *
+from top_block import *
 
 # create a couple of aliases
 serial_to_parallel = stream_to_vector
index 4699bb6fe18c10c55e595238fa45d1c7918cae0b..bc6402b8726ef2a0efaa941b095e528940246e8c 100644 (file)
@@ -1,5 +1,5 @@
 #
-# Copyright 2006 Free Software Foundation, Inc.
+# Copyright 2006,2007 Free Software Foundation, Inc.
 # 
 # This file is part of GNU Radio
 # 
@@ -19,9 +19,7 @@
 # Boston, MA 02110-1301, USA.
 # 
 
-from gnuradio_swig_python import hier_block2_swig, gr_make_runtime, \
-    runtime_run_unlocked, runtime_start_unlocked, runtime_stop_unlocked, \
-    runtime_wait_unlocked, runtime_restart_unlocked, io_signature
+from gnuradio_swig_python import hier_block2_swig
 
 #
 # This hack forces a 'has-a' relationship to look like an 'is-a' one.
@@ -77,34 +75,3 @@ class hier_block2(object):
         self._hb.disconnect(src_block.basic_block(), src_port,
                             dst_block.basic_block(), dst_port)
 
-# Convenience class to create a no input, no output block for runtime top block
-class top_block(hier_block2):
-    def __init__(self, name):
-        hier_block2.__init__(self, name, io_signature(0,0,0), io_signature(0,0,0))
-
-# This allows the 'run_locked' methods, which are defined in gr_runtime.i,
-# to release the Python global interpreter lock before calling the actual
-# method in gr.runtime
-#
-# This probably should be elsewhere but it works here
-class runtime(object):
-    def __init__(self, top_block):
-        if (isinstance(top_block, hier_block2)):
-            self._r = gr_make_runtime(top_block._hb)            
-        else:
-            self._r = gr_make_runtime(top_block)
-
-    def run(self):
-        runtime_run_unlocked(self._r)
-
-    def start(self):
-        runtime_start_unlocked(self._r)
-
-    def stop(self):
-        runtime_stop_unlocked(self._r)
-
-    def wait(self):
-        runtime_wait_unlocked(self._r)
-
-    def restart(self):
-        runtime_restart_unlocked(self._r)
index 9fa002501ab96157a68fc0bcfce0336c7e0ae41b..d07d4cb3894ccb08be362bde038e4b20407fbb23 100755 (executable)
@@ -100,8 +100,7 @@ class test_hier_block2(gr_unittest.TestCase):
         sink2 = gr.vector_sink_f()
         hblock.connect(src, sink1)
         hblock.connect(src, sink2)
-        runtime = gr.runtime(hblock)
-        runtime.run()
+        hblock.run()
         actual1 = sink1.data()
         actual2 = sink2.data()
         self.assertEquals(expected, actual1)
@@ -185,8 +184,7 @@ class test_hier_block2(gr_unittest.TestCase):
        src = gr.vector_source_f(data, False)
        dst = gr.vector_sink_f()
        hblock.connect(src, dst)
-       r = gr.runtime(hblock)
-       r.run()
+       hblock.run()
        self.assertEquals(data, dst.data())
 
 if __name__ == "__main__":
diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_runtime.py b/gnuradio-core/src/python/gnuradio/gr/qa_runtime.py
deleted file mode 100755 (executable)
index ce0bdde..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-#!/usr/bin/env python
-
-from gnuradio import gr, gr_unittest
-
-class test_runtime(gr_unittest.TestCase):
-
-    def setUp(self):
-       pass
-       
-    def tearDown(self):
-       pass
-
-    def test_001_run(self):
-       hblock = gr.hier_block2("test_block", 
-                               gr.io_signature(0,0,0), 
-                               gr.io_signature(0,0,0))
-       runtime = gr.runtime(hblock)
-       runtime.run()
-
-    def test_002_run_twice(self):
-       hblock = gr.hier_block2("test_block", 
-                               gr.io_signature(0,0,0), 
-                               gr.io_signature(0,0,0))
-       runtime = gr.runtime(hblock)
-       runtime.run()
-       self.assertRaises(RuntimeError, lambda: runtime.run())
-        
-if __name__ == "__main__":
-    gr_unittest.main()
diff --git a/gnuradio-core/src/python/gnuradio/gr/top_block.py b/gnuradio-core/src/python/gnuradio/gr/top_block.py
new file mode 100644 (file)
index 0000000..9b709c0
--- /dev/null
@@ -0,0 +1,91 @@
+#
+# 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.
+# 
+
+from gnuradio_swig_python import top_block_swig, \
+    top_block_wait_unlocked, top_block_run_unlocked
+
+#
+# This hack forces a 'has-a' relationship to look like an 'is-a' one.
+#
+# It allows Python classes to subclass this one, while passing through
+# method calls to the C++ class shared pointer from SWIG.
+#
+# It also allows us to intercept method calls if needed.
+#
+# This allows the 'run_locked' methods, which are defined in gr_top_block.i,
+# to release the Python global interpreter lock before calling the actual
+# method in gr_top_block
+#
+class top_block(object):
+    def __init__(self, name="top_block"):
+       self._tb = top_block_swig(name)
+
+    def __getattr__(self, name):
+       return getattr(self._tb, name)
+
+    def run(self):
+        top_block_run_unlocked(self._tb)
+
+    def wait(self):
+        top_block_wait_unlocked(self._tb)
+
+    # FIXME: these are duplicated from hier_block2.py; they should really be implemented
+    # in the original C++ class (gr_hier_block2), then they would all be inherited here
+
+    def connect(self, *points):
+        '''connect requires two or more arguments that can be coerced to endpoints.
+        If more than two arguments are provided, they are connected together successively.
+        '''
+        if len (points) < 2:
+            raise ValueError, ("connect requires at least two endpoints; %d provided." % (len (points),))
+        for i in range (1, len (points)):
+            self._connect(points[i-1], points[i])
+
+    def _connect(self, src, dst):
+        (src_block, src_port) = self._coerce_endpoint(src)
+        (dst_block, dst_port) = self._coerce_endpoint(dst)
+        self._tb.connect(src_block.basic_block(), src_port,
+                         dst_block.basic_block(), dst_port)
+
+    def _coerce_endpoint(self, endp):
+        if hasattr(endp, 'basic_block'):
+            return (endp, 0)
+        else:
+            if hasattr(endp, "__getitem__") and len(endp) == 2:
+                return endp # Assume user put (block, port)
+            else:
+                raise ValueError("unable to coerce endpoint")
+
+    def disconnect(self, *points):
+        '''connect requires two or more arguments that can be coerced to endpoints.
+        If more than two arguments are provided, they are disconnected successively.
+        '''
+        if len (points) < 2:
+            raise ValueError, ("disconnect requires at least two endpoints; %d provided." % (len (points),))
+        for i in range (1, len (points)):
+            self._disconnect(points[i-1], points[i])
+
+    def _disconnect(self, src, dst):
+        (src_block, src_port) = self._coerce_endpoint(src)
+        (dst_block, dst_port) = self._coerce_endpoint(dst)
+        self._tb.disconnect(src_block.basic_block(), src_port,
+                            dst_block.basic_block(), dst_port)
+
index 25436c1c806a30f96ffe2bdc6f7ca0d90657dbf6..41e9ee4d6101d337953547d5c2a5f314dbfd7caf 100644 (file)
@@ -21,4 +21,4 @@
 
 include $(top_srcdir)/Makefile.common
 
-SUBDIRS = python
+SUBDIRS = python c++
index 444bf11e3d8f5a4cc5ae90a010bd87feedcb2539..5ac086075ba323de6697c77d857bfce9128a78b7 100644 (file)
@@ -20,7 +20,4 @@
 # 
 
 include $(top_srcdir)/Makefile.common
-
-# FIXME: do not build automatically; need to detect required pre-requisites
-
 # SUBDIRS = dial_tone 
index cfc5458026a7ee94b1b5f93f83fec6f732af833c..6d5ed5059c074215eb4d2197254ca667d6f0ce66 100644 (file)
@@ -1,2 +1,16 @@
 This example requires that gr-audio-alsa be built in the main tree in order
 to compile successfully.  It is not built automatically.
+
+To build this example, you must make two modifications to the build system:
+
+1) Add the following line inside config/grc_gnuradio_examples.m4:
+
+   gnuradio-examples/c++/dial_tone/Makefile
+   
+   ...to the list of Makefiles already in there.
+   
+2) In gnuradio-examples/c++/Makefile.am, uncomment the SUBDIRS line
+
+# SUBDIRS = dial_tone
+
+Then, from the top-level directory, re-run ./bootstrap and ./configure.
\ No newline at end of file
index f87b5e60d7c4df4b325204e918be32687ea71abc..296cfcc115308d8de94d21fe778b880b8016dcd5 100644 (file)
@@ -32,9 +32,7 @@ dial_tone_sptr make_dial_tone()
 
 // Hierarchical block constructor, with no inputs or outputs
 dial_tone::dial_tone() : 
-gr_hier_block2("dial_tone",
-              gr_make_io_signature(0,0,0),
-              gr_make_io_signature(0,0,0))
+    gr_top_block("dial_tone")
 {
     gr_sig_source_f_sptr src0 = gr_make_sig_source_f(48000, GR_SIN_WAVE, 350, 0.1);
     gr_sig_source_f_sptr src1 = gr_make_sig_source_f(48000, GR_SIN_WAVE, 440, 0.1);
index 793f65b4ca66c2126de68c92a207dac180fff8be..c645439bbaa70ba834f8c2a0c95ae0d6c0d63192 100644 (file)
  * Boston, MA 02110-1301, USA.
  */
 
-#include <gr_hier_block2.h>
+#include <gr_top_block.h>
 
 class dial_tone;
 typedef boost::shared_ptr<dial_tone> dial_tone_sptr;
 dial_tone_sptr make_dial_tone();
 
-class dial_tone : public gr_hier_block2
+class dial_tone : public gr_top_block
 {
 private:
     dial_tone();
index 684b8efd3808762ea7a7d013a62131e0100cd19d..a09bd8288131bd832cabfb4d2d6274188c163015 100644 (file)
 // Tell the runtime to go...
 
 #include <dial_tone.h>
-#include <gr_runtime.h>
 
 int main()
 {
     dial_tone_sptr top_block = make_dial_tone();
-    gr_runtime_sptr runtime = gr_make_runtime(top_block);
-
-    runtime->run();   
+    top_block->run();   
     return 0;
 }
index a5010faa5dc52a72da2e2a823ac205320cd45996..70d1e53d206855957413d4612811fce37dc20444 100755 (executable)
@@ -60,13 +60,9 @@ if __name__ == '__main__':
                        options.audio_output, 
                        options.amplitude)
                              
-       # Create an instance of a runtime, passing it the top block
-       # to process
-       runtime = gr.runtime(top)
-
        try:    
                # Run forever
-               runtime.run()
+               top.run()
        except KeyboardInterrupt:
                # Ctrl-C exits
                pass
index bf562e0d962e7a359bdaec342ffeb35234521574..27259d8127f8d766a9265ca6f11d7854a9177672 100755 (executable)
@@ -51,13 +51,9 @@ def main():
        # Create an instance of a hierarchical block
        top_block = dect_receiver(options)
                              
-       # Create an instance of a runtime, passing it the top block
-       # to process
-       runtime = gr.runtime(top_block)
-
        try:    
             # Run forever
-            runtime.run()
+            top_block.run()
        except KeyboardInterrupt:
             # Ctrl-C exits
             pass
index a98d1cdfb40e2bbcc8136e2dc323c04f65f6456b..31dfb991ba1e5aaa555d58883a1ee4ece73c2411 100755 (executable)
@@ -155,10 +155,7 @@ def main():
         
     # Create an instance of a hierarchical block
     top_block = my_graph(mods[options.modulation], demods[options.modulation], rx_callback, options)
-    
-    # Create an instance of a runtime, passing it the top block
-    runtime = gr.runtime(top_block)
-    runtime.start()
+    top_block.start()
 
     # generate and send packets
     nbytes = int(1e6 * options.megabytes)
@@ -175,7 +172,7 @@ def main():
         
     send_pkt(eof=True)
 
-    runtime.wait()
+    top_block.wait()
     
 if __name__ == '__main__':
     try:
index 669d5618e707a9470fe6204533da7beb0ebf309f..c92d487bdc284e087de3ca3501e47df3a07f7fa8 100755 (executable)
@@ -95,12 +95,7 @@ def main():
 
     # Create an instance of a hierarchical block
     top_block = receive_path(demods[options.modulation], rx_callback, options)
-    
-    # Create an instance of a runtime, passing it the top block
-    runtime = gr.runtime(top_block)
-    runtime.start()
-
-    runtime.wait()         # wait for it to finish
+    top_block.run()    
 
 if __name__ == '__main__':
     try:
index 0059a4555ec9d7532e43b1ff711adcc787f04a8a..752cdff5536bff2e76be14e40a58ba58bda393b2 100755 (executable)
@@ -88,10 +88,7 @@ def main():
 
     # Create an instance of a hierarchical block
     top_block = transmit_path(mods[options.modulation], options)
-    
-    # Create an instance of a runtime, passing it the top block
-    runtime = gr.runtime(top_block)
-    runtime.start()
+    top_block.start()    
 
     # generate and send packets
     nbytes = int(1e6 * options.megabytes)
@@ -108,7 +105,7 @@ def main():
         pktno += 1
         
     send_pkt(eof=True)
-    runtime.wait()
+    top_block.wait()
 
 if __name__ == '__main__':
     try:
index 116a848150644fea66ada146134c68394199aaaf..e59d50834acbfa82fab2967e31ecfc28f0a35b32 100755 (executable)
@@ -50,12 +50,9 @@ if __name__ == '__main__':
     top_block = audio_sink(options.src_name, options.src_port,
                            options.packet_size, options.sample_rate)
     
-    # Create an instance of a runtime, passing it the top block
-    runtime = gr.runtime(top_block)
-    
     try:    
         # Run forever
-        runtime.run()
+        top_block.run()
     except KeyboardInterrupt:
         # Ctrl-C exits
         pass
index 2c42e29d3ffb5c29dbef2b800e96c5bd37da799f..d7f4f6d9369c41991c539c9d9f2b823a9cb6dec4 100755 (executable)
@@ -52,12 +52,9 @@ if __name__ == '__main__':
     top_block = audio_source(options.src_name, options.dst_name, options.dst_port,
                              options.packet_size, options.sample_rate)
     
-    # Create an instance of a runtime, passing it the top block
-    runtime = gr.runtime(top_block)
-    
     try:    
         # Run forever
-        runtime.run()
+        top_block.run()
     except KeyboardInterrupt:
         # Ctrl-C exits
         pass
index 5b979b35bfbe80f69e8d65884e4f0442a6b2357f..47d24b9bcfb006764e6180b63cc95503d0e81122 100755 (executable)
@@ -50,12 +50,9 @@ if __name__ == '__main__':
     top_block = dial_tone_sink(options.src_name, options.src_port,
                                options.packet_size, options.sample_rate)
     
-    # Create an instance of a runtime, passing it the top block
-    runtime = gr.runtime(top_block)
-    
     try:    
         # Run forever
-        runtime.run()
+        top_block.run()
     except KeyboardInterrupt:
         # Ctrl-C exits
         pass
index f092097d94e32c3b582796a4ed0234ba6819e1b4..835f9aafcb34558d97909a6ff21200ff64038a19 100755 (executable)
@@ -61,12 +61,9 @@ if __name__ == '__main__':
     top_block = dial_tone_source(options.src_name, options.dst_name, options.dst_port,
                                  options.packet_size, options.sample_rate)
     
-    # Create an instance of a runtime, passing it the top block
-    runtime = gr.runtime(top_block)
-    
     try:    
         # Run forever
-        runtime.run()
+        top_block.run()
     except KeyboardInterrupt:
         # Ctrl-C exits
         pass
index 05f3b0cbc1f3aa997d34499ee44b826b6ecd6a4d..981cc598b96178d9c33df76798502bcd2c52d7e9 100755 (executable)
@@ -48,12 +48,9 @@ if __name__ == "__main__":
     # Create an instance of a hierarchical block
     top_block = vector_sink(options.src_name, options.src_port, options.packet_size)
     
-    # Create an instance of a runtime, passing it the top block
-    runtime = gr.runtime(top_block)
-    
     try:    
         # Run forever
-        runtime.run()
+        top_block.run()
     except KeyboardInterrupt:
         # Ctrl-C exits
         pass
index 8ef01d7a90cdc7101be9d56138e4b3c2217d5b5b..e7ec2a461d15bbe15ddb91ff605864faabf74bf0 100755 (executable)
@@ -51,12 +51,9 @@ if __name__ == '__main__':
     top_block = vector_source(options.src_name, options.dst_name,
                               options.dst_port, options.packet_size)
     
-    # Create an instance of a runtime, passing it the top block
-    runtime = gr.runtime(top_block)
-    
     try:    
         # Run forever
-        runtime.run()
+        top_block.run()
     except KeyboardInterrupt:
         # Ctrl-C exits
         pass
index 54c612f6233656721fc027ff711a0e440d51b844..6b85281ad7f57887df5f6c0c02e69cb1a547b457 100755 (executable)
@@ -85,10 +85,9 @@ def main():
         sys.exit(1)
 
     top_block = usrp_sounder_rx(options)
-    runtime = gr.runtime(top_block)
 
     try:
-        runtime.run()
+        top_block.run()
     except KeyboardInterrupt:
         pass
 
index e7fc3f60bbae63b85c9656c78e4b9c1fd9a379af..ae531d5100253f766664786877a990b97fd593f1 100755 (executable)
@@ -99,13 +99,9 @@ def main():
                                    options.verbose, options.degree, options.chip_rate,
                                    options.amplitude)
                              
-       # Create an instance of a runtime, passing it the top block
-       # to process
-       runtime = gr.runtime(top_block)
-
        try:    
             # Run forever
-            runtime.run()
+            top_block.run()
        except KeyboardInterrupt:
             # Ctrl-C exits
             pass
index f1eb2a6bc07de00c361eb22319f12a55dd90d1ee..91a7a7affd9b75a7cce7a8b2d1124677b57ec96d 100755 (executable)
@@ -119,11 +119,9 @@ def main ():
     top_block = my_graph(options.type, options.amplitude, options.waveform_freq, options.offset,
                          options.tx_subdev_spec, options.interp, options.rf_freq)
 
-    runtime = gr.runtime(top_block)
-    
     try:    
         # Run forever
-        runtime.run()
+        top_block.run()
     except KeyboardInterrupt:
         # Ctrl-C exits
         pass
index 766ed483ce9b69f549de4e7138be8eb41cdcadd3..31d6d1dce6e1fd8b2c90142249ee4ed27465c1c6 100755 (executable)
@@ -160,10 +160,9 @@ def main():
     # Flow graph emits pages into message queue
     queue = gr.msg_queue()
     tb = app_top_block(options, queue)
-    r = gr.runtime(tb)
     
     try:
-        r.start()
+        tb.start()
        while 1:
            if not queue.empty_p():
                msg = queue.delete_head() # Blocking read
@@ -181,7 +180,7 @@ def main():
                time.sleep(1)
 
     except KeyboardInterrupt:
-        r.stop()
+        tb.stop()
 
 if __name__ == "__main__":
     main()
index 8e29eeee65340ad527a8089625bf61b0cf2be62e..daee3532cd59d7a21fdf85ac6a7c0ba5643f4d88 100755 (executable)
@@ -76,10 +76,9 @@ def main():
 
     queue = gr.msg_queue()
     tb = app_top_block(options, queue)
-    r = gr.runtime(tb)
 
     try:
-        r.start()
+        tb.start()
        while 1:
            if not queue.empty_p():
                msg = queue.delete_head() # Blocking read
@@ -96,7 +95,7 @@ def main():
                time.sleep(1)
 
     except KeyboardInterrupt:
-        r.stop()
+        tb.stop()
     
 if __name__ == "__main__":
     main()
index 69b0dbf80e7947ed797e6eb92a31a094169aad71..7f494191db98be69e54ac09694fc7bbf8339274b 100755 (executable)
@@ -76,10 +76,9 @@ def main():
 
     queue = gr.msg_queue()
     tb = app_top_block(options, queue)
-    r = gr.runtime(tb)
 
     try:
-        r.start()
+        tb.start()
        while 1:
            if not queue.empty_p():
                msg = queue.delete_head() # Blocking read
@@ -96,7 +95,7 @@ def main():
                time.sleep(1)
 
     except KeyboardInterrupt:
-        r.stop()
+        tb.stop()
     
 if __name__ == "__main__":
     main()
index 7b21d6b0ab33ec56a85cf74a263309b7db013365..e510f174c90bd9828f1b0ea0557d780987a4c919 100644 (file)
@@ -65,11 +65,11 @@ class stdframe (wx.Frame):
         vbox.Fit(self)
 
     def OnCloseWindow (self, event):
-        self.runtime().stop()
+        self.top_block().stop()
         self.Destroy ()
 
-    def runtime (self):
-        return self.panel.runtime
+    def top_block (self):
+        return self.panel.top_block
     
 class stdpanel (wx.Panel):
     def __init__ (self, parent, frame, top_block_maker):
@@ -83,8 +83,7 @@ class stdpanel (wx.Panel):
         self.SetAutoLayout (True)
         vbox.Fit (self)
 
-        self.runtime = gr.runtime(self.top_block)
-        self.runtime.start ()
+        self.top_block.start ()
 
 class std_top_block (gr.top_block):
     def __init__ (self, parent, panel, vbox, argv):