commit-gnuradio
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Commit-gnuradio] r4914 - in gnuradio/branches/developers/jcorgan/hier2/


From: jcorgan
Subject: [Commit-gnuradio] r4914 - in gnuradio/branches/developers/jcorgan/hier2/gnuradio-core/src: lib/runtime python/gnuradio/gr
Date: Sat, 7 Apr 2007 08:22:29 -0600 (MDT)

Author: jcorgan
Date: 2007-04-07 08:22:29 -0600 (Sat, 07 Apr 2007)
New Revision: 4914

Modified:
   
gnuradio/branches/developers/jcorgan/hier2/gnuradio-core/src/lib/runtime/gr_hier_block2.cc
   
gnuradio/branches/developers/jcorgan/hier2/gnuradio-core/src/lib/runtime/gr_hier_block2.h
   
gnuradio/branches/developers/jcorgan/hier2/gnuradio-core/src/lib/runtime/gr_hier_block2.i
   
gnuradio/branches/developers/jcorgan/hier2/gnuradio-core/src/lib/runtime/gr_hier_block2_detail.cc
   
gnuradio/branches/developers/jcorgan/hier2/gnuradio-core/src/lib/runtime/gr_hier_block2_detail.h
   
gnuradio/branches/developers/jcorgan/hier2/gnuradio-core/src/lib/runtime/gr_runtime.cc
   
gnuradio/branches/developers/jcorgan/hier2/gnuradio-core/src/lib/runtime/gr_runtime.h
   
gnuradio/branches/developers/jcorgan/hier2/gnuradio-core/src/lib/runtime/gr_runtime.i
   
gnuradio/branches/developers/jcorgan/hier2/gnuradio-core/src/lib/runtime/gr_runtime_impl.cc
   
gnuradio/branches/developers/jcorgan/hier2/gnuradio-core/src/lib/runtime/gr_runtime_impl.h
   
gnuradio/branches/developers/jcorgan/hier2/gnuradio-core/src/lib/runtime/gr_simple_flowgraph.h
   
gnuradio/branches/developers/jcorgan/hier2/gnuradio-core/src/lib/runtime/gr_simple_flowgraph_detail.cc
   
gnuradio/branches/developers/jcorgan/hier2/gnuradio-core/src/lib/runtime/gr_simple_flowgraph_detail.h
   
gnuradio/branches/developers/jcorgan/hier2/gnuradio-core/src/python/gnuradio/gr/hier_block2.py
   
gnuradio/branches/developers/jcorgan/hier2/gnuradio-core/src/python/gnuradio/gr/qa_hier_block2.py
Log:
Merged -r4703:4704 from jcorgan/hier into jcorgan/hier2

Modified: 
gnuradio/branches/developers/jcorgan/hier2/gnuradio-core/src/lib/runtime/gr_hier_block2.cc
===================================================================
--- 
gnuradio/branches/developers/jcorgan/hier2/gnuradio-core/src/lib/runtime/gr_hier_block2.cc
  2007-04-07 14:16:19 UTC (rev 4913)
+++ 
gnuradio/branches/developers/jcorgan/hier2/gnuradio-core/src/lib/runtime/gr_hier_block2.cc
  2007-04-07 14:22:29 UTC (rev 4914)
@@ -1,6 +1,6 @@
 /* -*- c++ -*- */
 /*
- * Copyright 2006 Free Software Foundation, Inc.
+ * Copyright 2006,2007 Free Software Foundation, Inc.
  * 
  * This file is part of GNU Radio
  * 
@@ -61,3 +61,10 @@
 {
     d_detail->connect(src_name, src_port, dst_name, dst_port);
 }
+
+void 
+gr_hier_block2::disconnect(const std::string &src_name, int src_port, 
+                           const std::string &dst_name, int dst_port)
+{
+    d_detail->disconnect(src_name, src_port, dst_name, dst_port);
+}

Modified: 
gnuradio/branches/developers/jcorgan/hier2/gnuradio-core/src/lib/runtime/gr_hier_block2.h
===================================================================
--- 
gnuradio/branches/developers/jcorgan/hier2/gnuradio-core/src/lib/runtime/gr_hier_block2.h
   2007-04-07 14:16:19 UTC (rev 4913)
+++ 
gnuradio/branches/developers/jcorgan/hier2/gnuradio-core/src/lib/runtime/gr_hier_block2.h
   2007-04-07 14:22:29 UTC (rev 4914)
@@ -1,6 +1,6 @@
 /* -*- c++ -*- */
 /*
- * Copyright 2006 Free Software Foundation, Inc.
+ * Copyright 2006,2007 Free Software Foundation, Inc.
  * 
  * This file is part of GNU Radio
  * 
@@ -62,6 +62,8 @@
     void define_component(const std::string &name, gr_basic_block_sptr 
basic_block);
     void connect(const std::string &src_name, int src_port, 
                  const std::string &dst_name, int dst_port);
+    void disconnect(const std::string &src_name, int src_port,
+                   const std::string &dst_name, int dst_port);
 };
 
 #endif /* INCLUDED_GR_HIER_BLOCK2_H */

Modified: 
gnuradio/branches/developers/jcorgan/hier2/gnuradio-core/src/lib/runtime/gr_hier_block2.i
===================================================================
--- 
gnuradio/branches/developers/jcorgan/hier2/gnuradio-core/src/lib/runtime/gr_hier_block2.i
   2007-04-07 14:16:19 UTC (rev 4913)
+++ 
gnuradio/branches/developers/jcorgan/hier2/gnuradio-core/src/lib/runtime/gr_hier_block2.i
   2007-04-07 14:22:29 UTC (rev 4914)
@@ -1,6 +1,6 @@
 /* -*- c++ -*- */
 /*
- * Copyright 2005 Free Software Foundation, Inc.
+ * Copyright 2005,2006,2007 Free Software Foundation, Inc.
  * 
  * This file is part of GNU Radio
  * 
@@ -49,4 +49,7 @@
     void connect(const std::string &src_name, int src_port,
                  const std::string &dst_name, int dst_port)
         throw (std::invalid_argument);
+    void disconnect(const std::string &src_name, int src_port,
+                    const std::string &dst_name, int dst_port)
+        throw (std::invalid_argument);
 };

Modified: 
gnuradio/branches/developers/jcorgan/hier2/gnuradio-core/src/lib/runtime/gr_hier_block2_detail.cc
===================================================================
--- 
gnuradio/branches/developers/jcorgan/hier2/gnuradio-core/src/lib/runtime/gr_hier_block2_detail.cc
   2007-04-07 14:16:19 UTC (rev 4913)
+++ 
gnuradio/branches/developers/jcorgan/hier2/gnuradio-core/src/lib/runtime/gr_hier_block2_detail.cc
   2007-04-07 14:22:29 UTC (rev 4914)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2006 Free Software Foundation, Inc.
+ * Copyright 2006,2007 Free Software Foundation, Inc.
  * 
  * This file is part of GNU Radio
  * 
@@ -29,199 +29,248 @@
 #include <stdexcept>
 #include <iostream>
 
+#define GR_HIER_BLOCK2_DETAIL_DEBUG 1
+
 gr_hier_block2_detail::gr_hier_block2_detail(gr_hier_block2 *owner) :
-d_owner(owner)
+  d_owner(owner)
 {
 }
 
 gr_hier_block2_detail::~gr_hier_block2_detail()
 {
-    d_owner = 0; // Don't use delete, we didn't allocate
+  d_owner = 0; // Don't use delete, we didn't allocate
 }
 
 gr_basic_block_sptr
 gr_hier_block2_detail::lookup_block(const std::string &name)
 {
-    gr_hier_component_miter_t p = d_components.find(name);
-    if (p != d_components.end())
-        return p->second;
-    else
-        return gr_basic_block_sptr();
+  gr_hier_component_miter_t p = d_components.find(name);
+  if (p != d_components.end())
+    return p->second;
+  else
+    return gr_basic_block_sptr();
 }
 
 void 
 gr_hier_block2_detail::define_component(const std::string &name, 
gr_basic_block_sptr block)
 {
-    if (!block)
-       throw std::invalid_argument("null block passed");
+  if (!block)
+    throw std::invalid_argument("null block passed");
 
-    if (name == "self")
-        throw std::invalid_argument("name is reserved");
+  if (name == "self" || name == "NC")
+    throw std::invalid_argument("name is reserved");
 
-    // TODO: reject names with '.' inside
-    
-    if (!lookup_block(name))
-        d_components[name] = block;
-    else
-        throw std::invalid_argument("name already in use");
+  if (name.find('.') != std::string::npos || 
+      name.find('/') != std::string::npos)
+    throw std::invalid_argument("illegal character in name");
+
+  if (!lookup_block(name))
+    d_components[name] = block;
+  else
+    throw std::invalid_argument("name already in use");
 }
 
 void 
 gr_hier_block2_detail::connect(const std::string &src_name, int src_port, 
                                const std::string &dst_name, int dst_port)
 {
-    gr_io_signature_sptr src_io_signature;
-    gr_io_signature_sptr dst_io_signature;
+  gr_io_signature_sptr src_io_signature;
+  gr_io_signature_sptr dst_io_signature;
     
-    // Check against our *input_signature* if we're wiring from one of our 
external inputs
+  // Check against our *input_signature* if we're wiring from one of our 
external inputs
+  if (src_name != "NC") {
     if (src_name == "self") 
-        src_io_signature = d_owner->input_signature();
+      src_io_signature = d_owner->input_signature();
     else {
-        gr_basic_block_sptr src_block = lookup_block(src_name);
-        if (!src_block)
-            throw std::invalid_argument("undefined src name");
-        src_io_signature = src_block->output_signature();
+      gr_basic_block_sptr src_block = lookup_block(src_name);
+      if (!src_block)
+       throw std::invalid_argument("undefined src name");
+      src_io_signature = src_block->output_signature();
     }
     
-    // Check against our *output_signature* if we're wiring to one of our 
external outputs
+    check_valid_port(src_io_signature, src_port);
+  }
+
+  // Check against our *output_signature* if we're wiring to one of our 
external outputs
+  if (dst_name != "NC") {
     if (dst_name == "self") 
-       dst_io_signature = d_owner->output_signature();
+      dst_io_signature = d_owner->output_signature();
     else {
-        gr_basic_block_sptr dst_block = lookup_block(dst_name);
-        if (!dst_block)
-            throw std::invalid_argument("undefined dst name");
-        dst_io_signature = dst_block->input_signature();
+      gr_basic_block_sptr dst_block = lookup_block(dst_name);
+      if (!dst_block)
+       throw std::invalid_argument("undefined dst name");
+      dst_io_signature = dst_block->input_signature();
     }
-    
-    // Check port numbers are valid
-    check_valid_port(src_io_signature, src_port);
+
     check_valid_port(dst_io_signature, dst_port);
-
-    // Check destination port not already in use
     check_dst_not_used(dst_name, dst_port);
+  }
 
-    // Check endpoint types match
+  // Check endpoint types match
+  if (src_name != "NC" && dst_name != "NC")
     check_type_match(src_io_signature, src_port, dst_io_signature, dst_port);
 
-    d_edges.push_back(gr_make_edge(src_name, src_port, dst_name, dst_port));
+  gr_edge_sptr edge = gr_make_edge(src_name, src_port, dst_name, dst_port);
+  d_edges.push_back(edge);
 }
 
 void 
+gr_hier_block2_detail::disconnect(const std::string &src_name, int src_port, 
+                                  const std::string &dst_name, int dst_port)
+{
+  for (gr_edge_viter_t p = d_edges.begin(); p != d_edges.end(); p++) {
+    if (((*p)->src_name() == src_name) && 
+        ((*p)->src_port() == src_port) && 
+        ((*p)->dst_name() == dst_name) && 
+        ((*p)->dst_port() == dst_port)) {
+      d_edges.erase(p);
+      return;
+    }
+  }
+
+  throw std::invalid_argument("edge to disconnect not found");
+}
+
+void 
 gr_hier_block2_detail::check_valid_port(gr_io_signature_sptr sig, int port)
 {
-    if (port < 0)
-        throw std::invalid_argument("port number must not be negative");
+  if (port < 0)
+    throw std::invalid_argument("port number must not be negative");
        
-    if (sig->max_streams() >= 0 && port >= sig->max_streams())
-        throw std::invalid_argument("port number exceeds max streams");
+  if (sig->max_streams() >= 0 && port >= sig->max_streams())
+    throw std::invalid_argument("port number exceeds max streams");
 }
 
 void 
 gr_hier_block2_detail::check_dst_not_used(const std::string name, int port)
 {
-    for (gr_edge_viter_t p = d_edges.begin(); p != d_edges.end(); p++)
-        if ((*p)->dst_name() == name && (*p)->dst_port() == port)
-            throw std::invalid_argument("destination port in use");
+  for (gr_edge_viter_t p = d_edges.begin(); p != d_edges.end(); p++)
+    if ((*p)->dst_name() == name && (*p)->dst_port() == port)
+      throw std::invalid_argument("destination port in use");
 }
 
 void 
 gr_hier_block2_detail::check_type_match(gr_io_signature_sptr src_sig, int 
src_port,
                                         gr_io_signature_sptr dst_sig, int 
dst_port)
 {
-    if (src_sig->sizeof_stream_item(src_port) != 
dst_sig->sizeof_stream_item(dst_port))
-        throw std::invalid_argument("type mismatch");
+  if (src_sig->sizeof_stream_item(src_port) != 
dst_sig->sizeof_stream_item(dst_port))
+    throw std::invalid_argument("type mismatch");
 }
 
 std::string
 gr_hier_block2_detail::prepend_prefix(const std::string &prefix, const 
std::string &str)
 {
-    return prefix + ((prefix == "") ? "" : ".") + str;
+  return prefix + ((prefix == "") ? "" : ".") + str;
 }
 
 gr_endpoint
 gr_hier_block2_detail::match_endpoint(const std::string &name, int port, bool 
is_input)
 {
-    for (gr_edge_viter_t p = d_edges.begin(); p != d_edges.end(); p++) {
-        if (is_input) {
-            if ((*p)->src_name() == name && (*p)->src_port() == port)
-                return resolve_endpoint((*p)->dst_name(), (*p)->dst_port(), 
"", !is_input);
-           }
-        else {
-            if ((*p)->dst_name() == name && (*p)->dst_port() == port)
-                return resolve_endpoint((*p)->src_name(), (*p)->src_port(), 
"", !is_input);
-        }
+  for (gr_edge_viter_t p = d_edges.begin(); p != d_edges.end(); p++) {
+    if (is_input) {
+      if ((*p)->src_name() == name && (*p)->src_port() == port)
+       return resolve_endpoint((*p)->dst_name(), (*p)->dst_port(), "", 
!is_input);
     }
+    else {
+      if ((*p)->dst_name() == name && (*p)->dst_port() == port)
+       return resolve_endpoint((*p)->src_name(), (*p)->src_port(), "", 
!is_input);
+    }
+  }
 
-    // Should never get here
-    throw std::runtime_error("unable to match endpoint");
+  // Should never get here
+  throw std::runtime_error("unable to match endpoint");
 }
 
 gr_endpoint
 gr_hier_block2_detail::resolve_endpoint(const std::string &name, int port, 
                                         const std::string &prefix, bool 
is_input)
 {
-    gr_basic_block_sptr basic_block = lookup_block(name);
+  gr_basic_block_sptr basic_block = lookup_block(name);
 
-    // Check if 'name' points to gr_block (leaf node)
-    gr_block_sptr block(boost::dynamic_pointer_cast<gr_block, 
gr_basic_block>(basic_block));
-    if (block)
-        return gr_endpoint(prepend_prefix(prefix, name), port);
+  // Check if 'name' points to gr_block (leaf node)
+  gr_block_sptr block(boost::dynamic_pointer_cast<gr_block, 
gr_basic_block>(basic_block));
+  if (block)
+    return gr_endpoint(prepend_prefix(prefix, name), port);
 
-    // Check if 'name' points to hierarchical block
-    gr_hier_block2_sptr 
hier_block2(boost::dynamic_pointer_cast<gr_hier_block2, 
gr_basic_block>(basic_block));
-    if (hier_block2) {
-        std::string child_prefix = prepend_prefix(prefix, name);
-        gr_endpoint match(hier_block2->d_detail->match_endpoint("self", port, 
!is_input));
-        return gr_endpoint(prepend_prefix(child_prefix, match.name()), 
match.port());
-    }
+  // Check if 'name' points to hierarchical block
+  gr_hier_block2_sptr hier_block2(boost::dynamic_pointer_cast<gr_hier_block2, 
gr_basic_block>(basic_block));
+  if (hier_block2) {
+    std::string child_prefix = prepend_prefix(prefix, name);
+    gr_endpoint match(hier_block2->d_detail->match_endpoint("self", port, 
!is_input));
+    return gr_endpoint(prepend_prefix(child_prefix, match.name()), 
match.port());
+  }
 
-    // Shouldn't ever get here
-    throw std::runtime_error("unable to resolve endpoint");
+  // Shouldn't ever get here
+  throw std::runtime_error("unable to resolve endpoint");
 }
 
 void
 gr_hier_block2_detail::flatten(gr_simple_flowgraph_sptr sfg, const std::string 
&prefix)
 {
-    flatten_components(sfg, prefix);
-    flatten_edges(sfg, prefix);
+  flatten_components(sfg, prefix);
+  flatten_edges(sfg, prefix);
 }
 
 void
 gr_hier_block2_detail::flatten_components(gr_simple_flowgraph_sptr sfg, const 
std::string &prefix)
 {
-    // Add my non-hierarchical components to the simple flowgraph, then recurse
-    for (gr_hier_component_miter_t p = d_components.begin(); p != 
d_components.end(); p++) {
-        std::string name = prepend_prefix(prefix, p->first);
+  // Add my non-hierarchical components to the simple flowgraph, then recurse
+  std::vector<std::string> names = calc_used_components();
 
-        gr_basic_block_sptr basic_block = p->second;
-        gr_block_sptr block(boost::dynamic_pointer_cast<gr_block, 
gr_basic_block>(basic_block));
-        if (block)     
-            sfg->define_component(name, block);
+  for (std::vector<std::string>::iterator p = names.begin(); p != names.end(); 
p++) {
+    gr_basic_block_sptr basic_block = lookup_block(*p);
+    std::string name = prepend_prefix(prefix, *p);
 
-        gr_hier_block2_sptr 
hier_block2(boost::dynamic_pointer_cast<gr_hier_block2, 
gr_basic_block>(basic_block));
-        if (hier_block2)
-            hier_block2->d_detail->flatten_components(sfg, name);
-    }
+    gr_block_sptr block(boost::dynamic_pointer_cast<gr_block, 
gr_basic_block>(basic_block));
+    if (block) 
+      sfg->define_component(name, block);
+
+    gr_hier_block2_sptr 
hier_block2(boost::dynamic_pointer_cast<gr_hier_block2, 
gr_basic_block>(basic_block));
+    if (hier_block2)
+      hier_block2->d_detail->flatten_components(sfg, name);
+  }
 }
 
 void
 gr_hier_block2_detail::flatten_edges(gr_simple_flowgraph_sptr sfg, const 
std::string &prefix)
 {
-    // Add my edges to the flow graph, resolving references to actual endpoints
-    for (gr_edge_viter_t p = d_edges.begin(); p != d_edges.end(); p++) {
-       // Connections to self get resolved/added by parent if actually 
connected
-        if ((*p)->src_name() == "self" || (*p)->dst_name() == "self")
-            continue;
+  // Add my edges to the flow graph, resolving references to actual endpoints
+  for (gr_edge_viter_t p = d_edges.begin(); p != d_edges.end(); p++) {
+    // Connections to self get resolved/added by parent if actually connected
+    if ((*p)->src_name() == "self" || (*p)->dst_name() == "self")
+      continue;
 
-        gr_endpoint src_endp = resolve_endpoint((*p)->src_name(), 
(*p)->src_port(), prefix, true);
-        gr_endpoint dst_endp = resolve_endpoint((*p)->dst_name(), 
(*p)->dst_port(), prefix, false);
-        sfg->connect(src_endp.name(), src_endp.port(), dst_endp.name(), 
dst_endp.port());
-    }
+    // Connections to "NC" are silently ignored
+    if ((*p)->src_name() == "NC" || (*p)->dst_name() == "NC")
+      continue;
 
-    // Recurse hierarchical children
-    for (gr_hier_component_miter_t p = d_components.begin(); p != 
d_components.end(); p++) {
-        gr_hier_block2_sptr 
hier_block2(boost::dynamic_pointer_cast<gr_hier_block2, 
gr_basic_block>(p->second));
-        if (hier_block2)
-            hier_block2->d_detail->flatten_edges(sfg, prepend_prefix(prefix, 
p->first));
-    }
+    gr_endpoint src_endp = resolve_endpoint((*p)->src_name(), 
(*p)->src_port(), prefix, true);
+    gr_endpoint dst_endp = resolve_endpoint((*p)->dst_name(), 
(*p)->dst_port(), prefix, false);
+    sfg->connect(src_endp.name(), src_endp.port(), dst_endp.name(), 
dst_endp.port());
+  }
+
+  // Recurse hierarchical children
+  for (gr_hier_component_miter_t p = d_components.begin(); p != 
d_components.end(); p++) {
+    gr_hier_block2_sptr 
hier_block2(boost::dynamic_pointer_cast<gr_hier_block2, 
gr_basic_block>(p->second));
+    if (hier_block2)
+      hier_block2->d_detail->flatten_edges(sfg, prepend_prefix(prefix, 
p->first));
+  }
 }
+
+std::vector<std::string>
+gr_hier_block2_detail::calc_used_components()
+{
+  std::vector<std::string> tmp, result;
+  std::insert_iterator<std::vector<std::string> > inserter(result, 
result.begin());
+
+  for (gr_edge_viter_t p = d_edges.begin(); p != d_edges.end(); p++) {
+    if ((*p)->src_name() != "NC")
+      tmp.push_back((*p)->dst_name());
+    if ((*p)->dst_name() != "NC")
+      tmp.push_back((*p)->src_name());
+  }
+
+  sort(tmp.begin(), tmp.end());
+  unique_copy(tmp.begin(), tmp.end(), inserter);
+  return result;
+}

Modified: 
gnuradio/branches/developers/jcorgan/hier2/gnuradio-core/src/lib/runtime/gr_hier_block2_detail.h
===================================================================
--- 
gnuradio/branches/developers/jcorgan/hier2/gnuradio-core/src/lib/runtime/gr_hier_block2_detail.h
    2007-04-07 14:16:19 UTC (rev 4913)
+++ 
gnuradio/branches/developers/jcorgan/hier2/gnuradio-core/src/lib/runtime/gr_hier_block2_detail.h
    2007-04-07 14:22:29 UTC (rev 4914)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2006 Free Software Foundation, Inc.
+ * Copyright 2006,2007 Free Software Foundation, Inc.
  * 
  * This file is part of GNU Radio
  * 
@@ -47,6 +47,8 @@
     gr_basic_block_sptr lookup_block(const std::string &name);
     void connect(const std::string &src_name, int src_port, 
                  const std::string &dst_name, int dst_port);
+    void disconnect(const std::string &src_name, int src_port, 
+                    const std::string &dst_name, int dst_port);
     void check_valid_port(gr_io_signature_sptr sig, int port);
     void check_dst_not_used(const std::string name, int port);
     void check_type_match(gr_io_signature_sptr src_sig, int src_port,
@@ -58,7 +60,8 @@
     gr_endpoint match_endpoint(const std::string &name, int port, bool 
is_input);
     gr_endpoint resolve_endpoint(const std::string &name, int port, 
                                  const std::string &prefix, bool is_input);
-    
+    std::vector<std::string> calc_used_components();
+
 public:
     ~gr_hier_block2_detail();
 };

Modified: 
gnuradio/branches/developers/jcorgan/hier2/gnuradio-core/src/lib/runtime/gr_runtime.cc
===================================================================
--- 
gnuradio/branches/developers/jcorgan/hier2/gnuradio-core/src/lib/runtime/gr_runtime.cc
      2007-04-07 14:16:19 UTC (rev 4913)
+++ 
gnuradio/branches/developers/jcorgan/hier2/gnuradio-core/src/lib/runtime/gr_runtime.cc
      2007-04-07 14:22:29 UTC (rev 4914)
@@ -1,6 +1,6 @@
 /* -*- c++ -*- */
 /*
- * Copyright 2006 Free Software Foundation, Inc.
+ * Copyright 2006,2007 Free Software Foundation, Inc.
  * 
  * This file is part of GNU Radio
  * 
@@ -34,57 +34,64 @@
 gr_runtime_sptr 
 gr_make_runtime(gr_hier_block2_sptr top_block)
 {
-    return gr_runtime_sptr(new gr_runtime(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);
-    s_runtime = this;
+  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;
+  s_runtime = 0; // we don't own this
+  delete d_impl;
 }
 
 // FIXME: This prevents using more than one gr_runtime instance
 static void 
 runtime_sigint_handler(int signum)
 {
-
-    if (s_runtime)
-        s_runtime->stop();
+  if (s_runtime)
+    s_runtime->stop();
 }
 
 void 
 gr_runtime::start()
 {
-    gr_local_sighandler sigint(SIGINT, runtime_sigint_handler);
+  gr_local_sighandler sigint(SIGINT, runtime_sigint_handler);
 
-    d_impl->start();
+  d_impl->start();
 }
 
 void 
 gr_runtime::stop()
 {
-    d_impl->stop();
+  d_impl->stop();
 }
 
 void 
 gr_runtime::wait()
 {
-    gr_local_sighandler sigint(SIGINT, runtime_sigint_handler);
+  gr_local_sighandler sigint(SIGINT, runtime_sigint_handler);
 
-    d_impl->wait();
+  d_impl->wait();
 }
 
 void 
 gr_runtime::run()
 {
-    gr_local_sighandler sigint(SIGINT, runtime_sigint_handler);
+  gr_local_sighandler sigint(SIGINT, runtime_sigint_handler);
 
-    d_impl->start();
-    d_impl->wait();
+  d_impl->start();
+  d_impl->wait();
 }
+
+void
+gr_runtime::restart()
+{
+  gr_local_sighandler sigint(SIGINT, runtime_sigint_handler);
+
+  d_impl->restart();
+}

Modified: 
gnuradio/branches/developers/jcorgan/hier2/gnuradio-core/src/lib/runtime/gr_runtime.h
===================================================================
--- 
gnuradio/branches/developers/jcorgan/hier2/gnuradio-core/src/lib/runtime/gr_runtime.h
       2007-04-07 14:16:19 UTC (rev 4913)
+++ 
gnuradio/branches/developers/jcorgan/hier2/gnuradio-core/src/lib/runtime/gr_runtime.h
       2007-04-07 14:22:29 UTC (rev 4914)
@@ -1,6 +1,6 @@
 /* -*- c++ -*- */
 /*
- * Copyright 2006 Free Software Foundation, Inc.
+ * Copyright 2006,2007 Free Software Foundation, Inc.
  * 
  * This file is part of GNU Radio
  * 
@@ -29,21 +29,57 @@
 
 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(gr_hier_block2_sptr top_block);
+  friend gr_runtime_sptr gr_make_runtime(gr_hier_block2_sptr top_block);
 
-    gr_runtime_impl *d_impl;
+  gr_runtime_impl *d_impl;
     
 public:
-    ~gr_runtime();
+  ~gr_runtime();
 
-    void start();
-    void stop();
-    void wait();
-    void run();
+  /*!
+   * 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();
 };
 
 #endif /* INCLUDED_GR_RUNTIME_H */

Modified: 
gnuradio/branches/developers/jcorgan/hier2/gnuradio-core/src/lib/runtime/gr_runtime.i
===================================================================
--- 
gnuradio/branches/developers/jcorgan/hier2/gnuradio-core/src/lib/runtime/gr_runtime.i
       2007-04-07 14:16:19 UTC (rev 4913)
+++ 
gnuradio/branches/developers/jcorgan/hier2/gnuradio-core/src/lib/runtime/gr_runtime.i
       2007-04-07 14:22:29 UTC (rev 4914)
@@ -1,6 +1,6 @@
 /* -*- c++ -*- */
 /*
- * Copyright 2004,2006 Free Software Foundation, Inc.
+ * Copyright 2004,2006,2007 Free Software Foundation, Inc.
  * 
  * This file is part of GNU Radio
  * 
@@ -36,6 +36,7 @@
     void start() throw (std::runtime_error);
     void stop() throw (std::runtime_error);
     void wait() throw (std::runtime_error);
+    void restart() throw (std::runtime_error);
 };
 
 %{
@@ -72,4 +73,10 @@
     r->wait();
 }
 
+void runtime_restart_unlocked(gr_runtime_sptr r) throw (std::runtime_error) 
+{
+    ensure_py_gil_state2 _lock;
+    r->restart();
+}
+
 %}

Modified: 
gnuradio/branches/developers/jcorgan/hier2/gnuradio-core/src/lib/runtime/gr_runtime_impl.cc
===================================================================
--- 
gnuradio/branches/developers/jcorgan/hier2/gnuradio-core/src/lib/runtime/gr_runtime_impl.cc
 2007-04-07 14:16:19 UTC (rev 4913)
+++ 
gnuradio/branches/developers/jcorgan/hier2/gnuradio-core/src/lib/runtime/gr_runtime_impl.cc
 2007-04-07 14:22:29 UTC (rev 4914)
@@ -52,56 +52,86 @@
 void
 gr_runtime_impl::start()
 {
-    if (d_running)
-        throw std::runtime_error("already running");
-    else
-        d_running = true;
+  if (d_running)
+    throw std::runtime_error("already running");
+  else
+    d_running = true;
 
-    d_sfg->d_detail->reset();
-    d_top_block->d_detail->flatten(d_sfg);
-    d_sfg->d_detail->validate();
-    d_sfg->d_detail->setup_connections();
+  // Create new simple flow graph by flattening hierarchical block
+  d_sfg->d_detail->reset();
+  d_top_block->d_detail->flatten(d_sfg);
 
-    d_graphs = d_sfg->d_detail->partition();
-    if (GR_RUNTIME_IMPL_DEBUG)
-        std::cout << "Flow graph has " << d_graphs.size()
-                  << " sub-graphs." << std::endl;
+  // Validate new simple flow graph and wire it up
+  d_sfg->d_detail->validate();
+  d_sfg->d_detail->setup_connections();
 
-    d_threads.clear();
-    for (std::vector<gr_block_vector_t>::iterator p = d_graphs.begin();
-         p != d_graphs.end(); p++) {
-        gr_scheduler_thread *thread = new gr_scheduler_thread(*p);
-        thread->start();
-        d_threads.push_back(thread);
-    }
+  // Execute scheduler threads
+  start_threads();
 }
 
 void
+gr_runtime_impl::start_threads()
+{
+  d_graphs = d_sfg->d_detail->partition();
+  if (GR_RUNTIME_IMPL_DEBUG)
+    std::cout << "Flow graph has " << d_graphs.size()
+             << " sub-graphs." << std::endl;
+
+  d_threads.clear();
+  for (std::vector<gr_block_vector_t>::iterator p = d_graphs.begin();
+       p != d_graphs.end(); p++) {
+    gr_scheduler_thread *thread = new gr_scheduler_thread(*p);
+    thread->start();
+    d_threads.push_back(thread);
+  }
+}
+
+void
 gr_runtime_impl::stop()
 {
-    if (!d_running)
-        throw std::runtime_error("not running");
+  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;
+  d_running = false;
 }
 
 void
 gr_runtime_impl::wait()
 {
-    void *dummy_status; // don't ever dereference this
+  void *dummy_status; // don't ever dereference this
 
-    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
-    }
+  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
+  }
 }
 
+void
+gr_runtime_impl::restart()
+{
+  if (!d_running)
+    throw std::runtime_error("not running");
+
+  // Stop scheduler threads and wait for completion
+  stop();
+  wait();
+  
+  // Create new simple flow graph 
+  gr_simple_flowgraph_sptr new_sfg = gr_make_simple_flowgraph();
+  d_top_block->d_detail->flatten(new_sfg);
+  new_sfg->validate();
+  new_sfg->d_detail->merge_connections(d_sfg);
+  // d_sfg = new_sfg;
+
+  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))
+  omni_thread(NULL, PRIORITY_NORMAL),
+  d_sts(gr_make_single_threaded_scheduler(graph))
 {
 }
 
@@ -111,28 +141,30 @@
 
 void gr_scheduler_thread::start()
 {
-    start_undetached();
+  start_undetached();
 }
 
 void *
 gr_scheduler_thread::run_undetached(void *arg)
 {
-    // First code to run in new thread context
+  // First code to run in new thread context
 
-    // Mask off SIGINT in this thread to gaurantee mainline thread gets signal
+  // 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);
+  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;
+  // Run the single-threaded scheduler
+  d_sts->run();
+  return 0;
 }
 
-void gr_scheduler_thread::stop()
+void
+gr_scheduler_thread::stop()
 {
-    d_sts->stop();
+  d_sts->stop();
 }
+

Modified: 
gnuradio/branches/developers/jcorgan/hier2/gnuradio-core/src/lib/runtime/gr_runtime_impl.h
===================================================================
--- 
gnuradio/branches/developers/jcorgan/hier2/gnuradio-core/src/lib/runtime/gr_runtime_impl.h
  2007-04-07 14:16:19 UTC (rev 4913)
+++ 
gnuradio/branches/developers/jcorgan/hier2/gnuradio-core/src/lib/runtime/gr_runtime_impl.h
  2007-04-07 14:22:29 UTC (rev 4914)
@@ -1,6 +1,6 @@
 /* -*- c++ -*- */
 /*
- * Copyright 2006 Free Software Foundation, Inc.
+ * Copyright 2006,2007 Free Software Foundation, Inc.
  * 
  * This file is part of GNU Radio
  * 
@@ -33,38 +33,56 @@
 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;    
+  gr_single_threaded_scheduler_sptr d_sts;    
 
 public:
-    gr_scheduler_thread(gr_block_vector_t graph);
-    ~gr_scheduler_thread();
+  gr_scheduler_thread(gr_block_vector_t graph);
+  ~gr_scheduler_thread();
 
-    virtual void *run_undetached(void *arg);
-    void start();
-    void stop();
+  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);
-    friend class gr_runtime;
+  gr_runtime_impl(gr_hier_block2_sptr top_block);
+  friend class gr_runtime;
     
-    bool                           d_running;
-    gr_hier_block2_sptr            d_top_block;
-    gr_simple_flowgraph_sptr       d_sfg;
-    std::vector<gr_block_vector_t> d_graphs;
-    gr_scheduler_thread_vector_t   d_threads;
+  bool                           d_running;
+  gr_hier_block2_sptr            d_top_block;
+  gr_simple_flowgraph_sptr       d_sfg;
+  std::vector<gr_block_vector_t> d_graphs;
+  gr_scheduler_thread_vector_t   d_threads;
             
-    void start();
-    void stop();
-    void wait();
-    
+  void start();
+  void start_threads();
+  void stop();
+  void wait();
+  void restart();
+
 public:
-    ~gr_runtime_impl();
+  ~gr_runtime_impl();
 
 };
 

Modified: 
gnuradio/branches/developers/jcorgan/hier2/gnuradio-core/src/lib/runtime/gr_simple_flowgraph.h
===================================================================
--- 
gnuradio/branches/developers/jcorgan/hier2/gnuradio-core/src/lib/runtime/gr_simple_flowgraph.h
      2007-04-07 14:16:19 UTC (rev 4913)
+++ 
gnuradio/branches/developers/jcorgan/hier2/gnuradio-core/src/lib/runtime/gr_simple_flowgraph.h
      2007-04-07 14:22:29 UTC (rev 4914)
@@ -1,6 +1,6 @@
 /* -*- c++ -*- */
 /*
- * Copyright 2006 Free Software Foundation, Inc.
+ * Copyright 2006,2007 Free Software Foundation, Inc.
  * 
  * This file is part of GNU Radio
  * 
@@ -31,22 +31,33 @@
 
 class gr_simple_flowgraph_detail;
 
+/*!
+ *\brief Class representing a low-level, "flattened" flow graph
+ *
+ * This class holds the results of the call to gr.hier_block2.flatten(),
+ * which is a graph that has only the connected blocks and edges of
+ * the original hier_block2, with all the hierarchy removed.
+ *
+ * While this class is exported to Python via SWIG for ease of QA
+ * testing, it is not used by application developers, and there is
+ * no way to feed this to a gr.runtime() instance.
+ */
 class gr_simple_flowgraph
 {
 private:
-    friend class gr_runtime_impl;
-    friend gr_simple_flowgraph_sptr gr_make_simple_flowgraph();
-    gr_simple_flowgraph();
+  friend class gr_runtime_impl;
+  friend gr_simple_flowgraph_sptr gr_make_simple_flowgraph();
+  gr_simple_flowgraph();
 
-    gr_simple_flowgraph_detail *d_detail;
+  gr_simple_flowgraph_detail *d_detail;
             
 public:
-    ~gr_simple_flowgraph();
+  ~gr_simple_flowgraph();
 
-    void define_component(const std::string &name, gr_block_sptr block);    
-    void connect(const std::string &src, int src_port, 
-                 const std::string &dst, int dst_port);
-    void validate();
+  void define_component(const std::string &name, gr_block_sptr block);    
+  void connect(const std::string &src, int src_port, 
+              const std::string &dst, int dst_port);
+  void validate();
 };
 
 #endif /* INCLUDED_GR_SIMPLE_FLOWGRAPH_H */

Modified: 
gnuradio/branches/developers/jcorgan/hier2/gnuradio-core/src/lib/runtime/gr_simple_flowgraph_detail.cc
===================================================================
--- 
gnuradio/branches/developers/jcorgan/hier2/gnuradio-core/src/lib/runtime/gr_simple_flowgraph_detail.cc
      2007-04-07 14:16:19 UTC (rev 4913)
+++ 
gnuradio/branches/developers/jcorgan/hier2/gnuradio-core/src/lib/runtime/gr_simple_flowgraph_detail.cc
      2007-04-07 14:22:29 UTC (rev 4914)
@@ -1,6 +1,6 @@
 /* -*- c++ -*- */
 /*
- * Copyright 2006 Free Software Foundation, Inc.
+ * Copyright 2006,2007 Free Software Foundation, Inc.
  *
  * This file is part of GNU Radio
  *
@@ -32,13 +32,13 @@
 #include <iostream>
 #include <stdexcept>
 
-#define GR_SIMPLE_FLOWGRAPH_DETAIL_DEBUG 0
+#define GR_SIMPLE_FLOWGRAPH_DETAIL_DEBUG 1
 
 gr_edge_sptr
 gr_make_edge(const std::string &src_name, int src_port,
             const std::string &dst_name, int dst_port)
 {
-    return gr_edge_sptr(new gr_edge(src_name, src_port, dst_name, dst_port));
+  return gr_edge_sptr(new gr_edge(src_name, src_port, dst_name, dst_port));
 }
 
 gr_edge::gr_edge(const std::string &src_name, int src_port, const std::string 
&dst_name, int dst_port)
@@ -52,8 +52,8 @@
 }
 
 gr_simple_flowgraph_detail::gr_simple_flowgraph_detail() :
-d_components(),
-d_edges()
+  d_components(),
+  d_edges()
 {
 }
 
@@ -64,162 +64,161 @@
 void
 gr_simple_flowgraph_detail::reset()
 {
-    // Boost shared pointers will deallocate as needed
-    d_edges.clear();
-    d_components.clear();
+  // Boost shared pointers will deallocate as needed
+  d_edges.clear();
+  d_components.clear();
 }
 
 gr_block_sptr
 gr_simple_flowgraph_detail::lookup_block(const std::string &name)
 {
-    gr_component_miter_t p = d_components.find(name);
-    if (p != d_components.end())
-        return p->second;
-    else
-        return gr_block_sptr();
+  gr_component_miter_t p = d_components.find(name);
+  if (p != d_components.end())
+    return p->second;
+  else
+    return gr_block_sptr();
 }
 
 std::string
 gr_simple_flowgraph_detail::lookup_name(gr_block_sptr block)
 {
-    for (gr_component_miter_t p = d_components.begin(); p != 
d_components.end(); p++) {
-        if (p->second == block)
-            return p->first;
-    }
+  for (gr_component_miter_t p = d_components.begin(); p != d_components.end(); 
p++) {
+    if (p->second == block)
+      return p->first;
+  }
 
-    return std::string(""); // Not found
+  return std::string(""); // Not found
 }
 
 void
 gr_simple_flowgraph_detail::define_component(const std::string &name, 
gr_block_sptr block)
 {
-    if (!block)
-        throw std::invalid_argument("null block passed");
+  if (!block)
+    throw std::invalid_argument("null block passed");
 
-    if (!lookup_block(name))
-        d_components[name] = block;
-    else
-        throw std::invalid_argument("name already in use");
+  if (!lookup_block(name))
+    d_components[name] = block;
+  else
+    throw std::invalid_argument("name already in use");
 }
 
 void
 gr_simple_flowgraph_detail::connect(const std::string &src_name, int src_port,
                                     const std::string &dst_name, int dst_port)
 {
-    gr_block_sptr src_block = lookup_block(src_name);
-    gr_block_sptr dst_block = lookup_block(dst_name);
+  gr_block_sptr src_block = lookup_block(src_name);
+  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;
+  if (GR_SIMPLE_FLOWGRAPH_DETAIL_DEBUG)
+    std::cout << "SFG connecting " << src_name << ":" << src_port << "->"
+             << dst_name << ":" << dst_port << std::endl;
 
-    if (!src_block)
-        throw std::invalid_argument("unknown src name");
-    if (!dst_block)
-        throw std::invalid_argument("unknown dst name");
+  if (!src_block)
+    throw std::invalid_argument("unknown src name");
+  if (!dst_block)
+    throw std::invalid_argument("unknown dst name");
 
-    check_valid_port(src_block->output_signature(), src_port);
-    check_valid_port(dst_block->input_signature(), dst_port);
-    check_dst_not_used(dst_name, dst_port);
-    check_type_match(src_block, src_port, dst_block, dst_port);
+  check_valid_port(src_block->output_signature(), src_port);
+  check_valid_port(dst_block->input_signature(), dst_port);
+  check_dst_not_used(dst_name, dst_port);
+  check_type_match(src_block, src_port, dst_block, dst_port);
 
-    d_edges.push_back(gr_make_edge(src_name, src_port, dst_name, dst_port));
+  d_edges.push_back(gr_make_edge(src_name, src_port, dst_name, dst_port));
 }
 
 void
 gr_simple_flowgraph_detail::check_valid_port(gr_io_signature_sptr sig, int 
port)
 {
-    if (port < 0)
-        throw std::invalid_argument("negative port number");
-    if (sig->max_streams() >= 0 && port >= sig->max_streams())
-        throw std::invalid_argument("port number exceeds max");
+  if (port < 0)
+    throw std::invalid_argument("negative port number");
+  if (sig->max_streams() >= 0 && port >= sig->max_streams())
+    throw std::invalid_argument("port number exceeds max");
 }
 
 void
 gr_simple_flowgraph_detail::check_dst_not_used(const std::string &name, int 
port)
 {
-    for (gr_edge_viter_t p = d_edges.begin(); p != d_edges.end(); p++)
-       if ((*p)->dst_name() == name && (*p)->dst_port() == port)
-           throw std::invalid_argument("dst already in use");
+  for (gr_edge_viter_t p = d_edges.begin(); p != d_edges.end(); p++)
+    if ((*p)->dst_name() == name && (*p)->dst_port() == port)
+      throw std::invalid_argument("dst already in use");
 }
 
 void
 gr_simple_flowgraph_detail::check_type_match(gr_block_sptr src_block, int 
src_port,
                                              gr_block_sptr dst_block, int 
dst_port)
 {
-    int src_size = src_block->output_signature()->sizeof_stream_item(src_port);
-    int dst_size = dst_block->input_signature()->sizeof_stream_item(dst_port);
+  int src_size = src_block->output_signature()->sizeof_stream_item(src_port);
+  int dst_size = dst_block->input_signature()->sizeof_stream_item(dst_port);
 
-    if (src_size != dst_size)
-        throw std::invalid_argument("type size mismatch");
+  if (src_size != dst_size)
+    throw std::invalid_argument("type size mismatch");
 }
 
 void
 gr_simple_flowgraph_detail::validate()
 {
-    for (gr_component_miter_t p = d_components.begin(); p != 
d_components.end(); p++) {
-       std::vector<int> used_ports;
-       int ninputs, noutputs;
+  for (gr_component_miter_t p = d_components.begin(); p != d_components.end(); 
p++) {
+    std::vector<int> used_ports;
+    int ninputs, noutputs;
 
-        used_ports = calc_used_ports(p->first, true); // inputs
-       ninputs = used_ports.size();
-       check_contiguity(p->second, used_ports, true); // inputs
+    used_ports = calc_used_ports(p->first, true); // inputs
+    ninputs = used_ports.size();
+    check_contiguity(p->second, used_ports, true); // inputs
 
-       used_ports = calc_used_ports(p->first, false); // outputs
-       noutputs = used_ports.size();
-       check_contiguity(p->second, used_ports, false); // outputs
+    used_ports = calc_used_ports(p->first, false); // outputs
+    noutputs = used_ports.size();
+    check_contiguity(p->second, used_ports, false); // outputs
 
-       if (!(p->second->check_topology(ninputs, noutputs)))
-           throw std::runtime_error("check topology failed");
-    }
+    if (!(p->second->check_topology(ninputs, noutputs)))
+      throw std::runtime_error("check topology failed");
+  }
 }
 
 std::vector<int>
 gr_simple_flowgraph_detail::calc_used_ports(const std::string &name, bool 
check_inputs)
 {
-    if (GR_SIMPLE_FLOWGRAPH_DETAIL_DEBUG)
-        std::cout << "Calculating used " << (check_inputs ? "input " : "output 
")
-                  << "ports...";
+  if (GR_SIMPLE_FLOWGRAPH_DETAIL_DEBUG)
+    std::cout << "Calculating used " << (check_inputs ? "input " : "output ")
+             << "ports...";
 
-    std::vector<int> tmp, result;
-    std::insert_iterator<std::vector<int> > inserter(result, result.begin());
+  std::vector<int> tmp, result;
+  std::insert_iterator<std::vector<int> > inserter(result, result.begin());
 
-    gr_edge_vector_t edges = calc_connections(name, check_inputs);
+  gr_edge_vector_t edges = calc_connections(name, check_inputs);
+  for (gr_edge_viter_t p = edges.begin(); p != edges.end(); p++) {
+    if (check_inputs == true)
+      tmp.push_back((*p)->dst_port());
+    else
+      tmp.push_back((*p)->src_port());
+  }
 
-    for (gr_edge_viter_t p = edges.begin(); p != edges.end(); p++) {
-        if (check_inputs == true)
-            tmp.push_back((*p)->dst_port());
-        else
-            tmp.push_back((*p)->src_port());
-    }
+  // remove duplicates
+  std::sort(tmp.begin(), tmp.end());
+  std::unique_copy(tmp.begin(), tmp.end(), inserter);
 
-    // remove duplicates
-    std::sort(tmp.begin(), tmp.end());
-    std::unique_copy(tmp.begin(), tmp.end(), inserter);
+  if (GR_SIMPLE_FLOWGRAPH_DETAIL_DEBUG)
+    std::cout << result.size() << std::endl;
 
-    if (GR_SIMPLE_FLOWGRAPH_DETAIL_DEBUG)
-        std::cout << result.size() << std::endl;
-
-    return result;
+  return result;
 }
 
 gr_edge_vector_t
 gr_simple_flowgraph_detail::calc_connections(const std::string &name, bool 
check_inputs)
 {
-    gr_edge_vector_t result;
+  gr_edge_vector_t result;
 
-    for (gr_edge_viter_t p = d_edges.begin(); p != d_edges.end(); p++) {
-        if (check_inputs) {
-            if ((*p)->dst_name() == name)
-                result.push_back(*p);
-        }
-        else {
-            if ((*p)->src_name() == name)
-                result.push_back(*p);
-        }
+  for (gr_edge_viter_t p = d_edges.begin(); p != d_edges.end(); p++) {
+    if (check_inputs) {
+      if ((*p)->dst_name() == name)
+       result.push_back(*p);
     }
+    else {
+      if ((*p)->src_name() == name)
+       result.push_back(*p);
+    }
+  }
 
-    return result;    // assumes no duplicates
+  return result;    // assumes no duplicates
 }
 
 void
@@ -227,335 +226,346 @@
                                              const std::vector<int> 
&used_ports,
                                              bool check_inputs)
 {
-    if (GR_SIMPLE_FLOWGRAPH_DETAIL_DEBUG)
-        std::cout << "Checking " << (check_inputs ? "input " : "output ")
-                  << "contiguity...";
+  if (GR_SIMPLE_FLOWGRAPH_DETAIL_DEBUG)
+    std::cout << "Checking " << (check_inputs ? "input " : "output ")
+             << "contiguity...";
 
-    gr_io_signature_sptr sig =
-        check_inputs ? block->input_signature() : block->output_signature();
+  gr_io_signature_sptr sig =
+    check_inputs ? block->input_signature() : block->output_signature();
 
-    int nports = used_ports.size();
-    int min_ports = sig->min_streams();
+  int nports = used_ports.size();
+  int min_ports = sig->min_streams();
 
-    if (nports == 0) {
-        if (min_ports == 0) {
-            if (GR_SIMPLE_FLOWGRAPH_DETAIL_DEBUG)
-                std::cout << "ok." << std::endl;
-            return;
-        }
-        else {
-            if (GR_SIMPLE_FLOWGRAPH_DETAIL_DEBUG)
-                std::cout << "needs " << min_ports << ", only has "
-                          << nports << std::endl;
-
-            throw std::runtime_error("insufficient ports");
-        }
+  if (nports == 0) {
+    if (min_ports == 0) {
+      if (GR_SIMPLE_FLOWGRAPH_DETAIL_DEBUG)
+       std::cout << "ok." << std::endl;
+      return;
     }
+    else {
+      if (GR_SIMPLE_FLOWGRAPH_DETAIL_DEBUG)
+       std::cout << "needs " << min_ports << ", only has "
+                 << nports << std::endl;
+      throw std::runtime_error("insufficient ports");
+    }
+  }
 
-    if (used_ports[nports-1]+1 != nports) {
-        for (int i = 0; i < nports; i++) {
-            if (used_ports[i] != i) {
-                if (GR_SIMPLE_FLOWGRAPH_DETAIL_DEBUG)
-                       std::cout << "missing " << (check_inputs ? "input 
":"output ")
-                              << i << std::endl;
+  if (used_ports[nports-1]+1 != nports) {
+    for (int i = 0; i < nports; i++) {
+      if (used_ports[i] != i) {
+       if (GR_SIMPLE_FLOWGRAPH_DETAIL_DEBUG)
+         std::cout << "missing " << (check_inputs ? "input ":"output ")
+                   << i << std::endl;
 
-                throw std::runtime_error("missing input assignment");
-               }
-           }
+       throw std::runtime_error("missing input assignment");
+      }
     }
+  }
 
-    if (GR_SIMPLE_FLOWGRAPH_DETAIL_DEBUG)
-        std::cout << "ok." << std::endl;
+  if (GR_SIMPLE_FLOWGRAPH_DETAIL_DEBUG)
+    std::cout << "ok." << std::endl;
 }
 
 void
 gr_simple_flowgraph_detail::setup_connections()
 {
-    // Assign block details to component blocks
-    for (gr_component_miter_t p = d_components.begin(); p != 
d_components.end(); p++) {
-        if (GR_SIMPLE_FLOWGRAPH_DETAIL_DEBUG)
-            std::cout << "Allocating output buffers for " << p->first << "..." 
<< std::endl;
+  // Assign block details to component blocks
+  for (gr_component_miter_t p = d_components.begin(); p != d_components.end(); 
p++) {
+    if (GR_SIMPLE_FLOWGRAPH_DETAIL_DEBUG)
+      std::cout << "Allocating output buffers for " << p->first << "..." << 
std::endl;
 
-        int ninputs = calc_used_ports(p->first, true).size();
-        int noutputs = calc_used_ports(p->first, false).size();
-        gr_block_detail_sptr detail = gr_make_block_detail(ninputs, noutputs);
-        for (int i = 0; i < noutputs; i++)
-            detail->set_output(i, allocate_buffer(p->first, i));
-        p->second->set_detail(detail);
-    }
+    int ninputs = calc_used_ports(p->first, true).size();
+    int noutputs = calc_used_ports(p->first, false).size();
+    gr_block_detail_sptr detail = gr_make_block_detail(ninputs, noutputs);
+    for (int i = 0; i < noutputs; i++)
+      detail->set_output(i, allocate_buffer(p->first, i));
+    p->second->set_detail(detail);
+  }
 
-    // Connect inputs to outputs for each block
-    for(gr_component_miter_t p = d_components.begin(); p != 
d_components.end(); p++) {
-        // Get its detail and edges that feed into it
-        gr_block_detail_sptr detail = p->second->detail();
-        gr_edge_vector_t in_edges = calc_upstream_edges(p->first);
+  // Connect inputs to outputs for each block
+  for(gr_component_miter_t p = d_components.begin(); p != d_components.end(); 
p++) {
+    // Get its detail and edges that feed into it
+    gr_block_detail_sptr detail = p->second->detail();
+    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 (GR_SIMPLE_FLOWGRAPH_DETAIL_DEBUG)
+      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++) {
-            // Set the input buffer on the destination port to the output
-            // buffer on the source port
-            int dst_port = (*e)->dst_port();
-            int src_port = (*e)->src_port();
-            gr_block_sptr src_block = lookup_block((*e)->src_name());
-            gr_buffer_sptr src_buffer = src_block->detail()->output(src_port);
+    // For each edge that feeds into it
+    for (gr_edge_viter_t e = in_edges.begin(); e != in_edges.end(); e++) {
+      // Set the input reader on the destination port to the output
+      // buffer on the source port
+      int dst_port = (*e)->dst_port();
+      int src_port = (*e)->src_port();
+      gr_block_sptr src_block = lookup_block((*e)->src_name());
+      gr_buffer_sptr src_buffer = src_block->detail()->output(src_port);
 
-            if (GR_SIMPLE_FLOWGRAPH_DETAIL_DEBUG)
-                std::cout << "Setting input on " << (*e)->dst_name()
-                          << ":" << dst_port << std::endl;
+      if (GR_SIMPLE_FLOWGRAPH_DETAIL_DEBUG)
+       std::cout << "Setting input on " << (*e)->dst_name()
+                 << ":" << dst_port << std::endl;
 
-            detail->set_input(dst_port, gr_buffer_add_reader(src_buffer, 
p->second->history()-1));
-        }
+      detail->set_input(dst_port, gr_buffer_add_reader(src_buffer, 
p->second->history()-1));
     }
+  }
 }
 
 gr_buffer_sptr
 gr_simple_flowgraph_detail::allocate_buffer(const std::string &name, int port)
 {
-    gr_block_sptr block = lookup_block(name);
-    int item_size = block->output_signature()->sizeof_stream_item(port);
-    int nitems = s_fixed_buffer_size/item_size;
+  gr_block_sptr block = lookup_block(name);
+  int item_size = block->output_signature()->sizeof_stream_item(port);
+  int nitems = s_fixed_buffer_size/item_size;
 
-    // Make sure there are at least twice the output_multiple no. of items
-    if (nitems < 2*block->output_multiple())   // Note: this means 
output_multiple()
-        nitems = 2*block->output_multiple();   // can't be changed by block 
dynamically
+  // Make sure there are at least twice the output_multiple no. of items
+  if (nitems < 2*block->output_multiple())     // Note: this means 
output_multiple()
+    nitems = 2*block->output_multiple();       // can't be changed by block 
dynamically
 
-    // If any downstream blocks are decimators and/or have a large 
output_multiple,
-    // ensure we have a buffer at least twice their decimation 
factor*output_multiple
-    gr_block_vector_t blocks = calc_downstream_blocks(name, port);
-    for (gr_block_viter_t p = blocks.begin(); p != blocks.end(); p++) {
-        int decimation = (int)(1.0/(*p)->relative_rate());
-        int multiple   = (*p)->output_multiple();
-        int history    = (*p)->history();
-        nitems = std::max(nitems, 2*(decimation*multiple+history));
-    }
+  // If any downstream blocks are decimators and/or have a large 
output_multiple,
+  // ensure we have a buffer at least twice their decimation 
factor*output_multiple
+  gr_block_vector_t blocks = calc_downstream_blocks(name, port);
+  for (gr_block_viter_t p = blocks.begin(); p != blocks.end(); p++) {
+    int decimation = (int)(1.0/(*p)->relative_rate());
+    int multiple   = (*p)->output_multiple();
+    int history    = (*p)->history();
+    nitems = std::max(nitems, 2*(decimation*multiple+history));
+  }
 
-    if (GR_SIMPLE_FLOWGRAPH_DETAIL_DEBUG)
-        std::cout << "Allocating buffer for port " << port << " with "
-                  << nitems << " items of size " << item_size << std::endl;
+  if (GR_SIMPLE_FLOWGRAPH_DETAIL_DEBUG)
+    std::cout << "Allocating buffer for port " << port << " with "
+             << nitems << " items of size " << item_size << std::endl;
 
-    return gr_make_buffer(nitems, item_size);
+  return gr_make_buffer(nitems, item_size);
 }
 
 gr_block_vector_t
 gr_simple_flowgraph_detail::calc_downstream_blocks(const std::string &name, 
int port)
 {
-    gr_block_vector_t tmp, result;
-    std::insert_iterator<gr_block_vector_t> inserter(result, result.begin());
+  gr_block_vector_t tmp, result;
+  std::insert_iterator<gr_block_vector_t> inserter(result, result.begin());
 
-    for (gr_edge_viter_t p = d_edges.begin(); p != d_edges.end(); p++)
-        if ((*p)->src_name() == name && (*p)->src_port() == port)
-            tmp.push_back(lookup_block((*p)->dst_name()));
+  for (gr_edge_viter_t p = d_edges.begin(); p != d_edges.end(); p++)
+    if ((*p)->src_name() == name && (*p)->src_port() == port)
+      tmp.push_back(lookup_block((*p)->dst_name()));
 
-    // Remove duplicates
-    sort(tmp.begin(), tmp.end());
-    unique_copy(tmp.begin(), tmp.end(), inserter);
-    return result;
+  // Remove duplicates
+  sort(tmp.begin(), tmp.end());
+  unique_copy(tmp.begin(), tmp.end(), inserter);
+  return result;
 }
 
 gr_block_vector_t
 gr_simple_flowgraph_detail::calc_downstream_blocks(const std::string &name)
 {
-    gr_block_vector_t tmp, result;
-    std::insert_iterator<gr_block_vector_t> inserter(result, result.begin());
+  gr_block_vector_t tmp, result;
+  std::insert_iterator<gr_block_vector_t> inserter(result, result.begin());
 
-    for (gr_edge_viter_t p = d_edges.begin(); p != d_edges.end(); p++)
-        if ((*p)->src_name() == name)
-            tmp.push_back(lookup_block((*p)->dst_name()));
+  for (gr_edge_viter_t p = d_edges.begin(); p != d_edges.end(); p++)
+    if ((*p)->src_name() == name)
+      tmp.push_back(lookup_block((*p)->dst_name()));
 
-    // Remove duplicates
-    sort(tmp.begin(), tmp.end());
-    unique_copy(tmp.begin(), tmp.end(), inserter);
-    return result;
+  // Remove duplicates
+  sort(tmp.begin(), tmp.end());
+  unique_copy(tmp.begin(), tmp.end(), inserter);
+  return result;
 }
 
 gr_edge_vector_t
 gr_simple_flowgraph_detail::calc_upstream_edges(const std::string &name)
 {
-    gr_edge_vector_t result;
+  gr_edge_vector_t result;
 
-    for (gr_edge_viter_t p = d_edges.begin(); p != d_edges.end(); p++)
-        if ((*p)->dst_name() == name)
-            result.push_back(*p);
+  for (gr_edge_viter_t p = d_edges.begin(); p != d_edges.end(); p++)
+    if ((*p)->dst_name() == name)
+      result.push_back(*p);
 
-    return result; // Assume no duplicates
+  return result; // Assume no duplicates
 }
 
 gr_block_vector_t
 gr_simple_flowgraph_detail::calc_used_blocks()
 {
-    std::vector<std::string> tmp, tmp_unique;
-    std::insert_iterator<std::vector<std::string> > inserter(tmp_unique, 
tmp_unique.begin());
-    gr_block_vector_t result;
+  std::vector<std::string> tmp, tmp_unique;
+  std::insert_iterator<std::vector<std::string> > inserter(tmp_unique, 
tmp_unique.begin());
+  gr_block_vector_t result;
 
-    for (gr_edge_viter_t p = d_edges.begin(); p != d_edges.end(); p++) {
-        tmp.push_back((*p)->src_name());
-        tmp.push_back((*p)->dst_name());
-    }
+  for (gr_edge_viter_t p = d_edges.begin(); p != d_edges.end(); p++) {
+    tmp.push_back((*p)->src_name());
+    tmp.push_back((*p)->dst_name());
+  }
 
-    sort(tmp.begin(), tmp.end());
-    unique_copy(tmp.begin(), tmp.end(), inserter);
+  sort(tmp.begin(), tmp.end());
+  unique_copy(tmp.begin(), tmp.end(), inserter);
 
-    for (std::vector<std::string>::iterator p = tmp_unique.begin();
-         p != tmp_unique.end(); p++)
-        result.push_back(lookup_block(*p));
+  for (std::vector<std::string>::iterator p = tmp_unique.begin();
+       p != tmp_unique.end(); p++)
+    result.push_back(lookup_block(*p));
 
-    if (GR_SIMPLE_FLOWGRAPH_DETAIL_DEBUG)
-        std::cout << "Flowgraph uses " << result.size()
-                  << " distinct blocks." << std::endl;
+  if (GR_SIMPLE_FLOWGRAPH_DETAIL_DEBUG)
+    std::cout << "Flowgraph uses " << result.size()
+             << " distinct blocks." << std::endl;
 
-    return result;
+  return result;
 }
 
 std::vector<gr_block_vector_t>
 gr_simple_flowgraph_detail::partition()
 {
-    std::vector<gr_block_vector_t> result;
-    gr_block_vector_t blocks = calc_used_blocks();
-    gr_block_vector_t graph;
+  std::vector<gr_block_vector_t> result;
+  gr_block_vector_t blocks = calc_used_blocks();
+  gr_block_vector_t graph;
 
-    while (blocks.size() > 0) {
-        graph = calc_reachable_blocks(blocks[0], blocks);
-        assert(graph.size());
-        result.push_back(topological_sort(graph));
+  while (blocks.size() > 0) {
+    graph = calc_reachable_blocks(blocks[0], blocks);
+    assert(graph.size());
+    result.push_back(topological_sort(graph));
 
-        for (gr_block_viter_t p = graph.begin(); p != graph.end(); p++)
-            blocks.erase(find(blocks.begin(), blocks.end(), *p));
-    }
+    for (gr_block_viter_t p = graph.begin(); p != graph.end(); p++)
+      blocks.erase(find(blocks.begin(), blocks.end(), *p));
+  }
 
-    return result;
+  return result;
 }
 
 gr_block_vector_t
 gr_simple_flowgraph_detail::calc_reachable_blocks(gr_block_sptr block, 
gr_block_vector_t &blocks)
 {
-    gr_block_vector_t result;
+  gr_block_vector_t result;
 
-    // Mark all blocks as unvisited
-    for (gr_block_viter_t p = blocks.begin(); p != blocks.end(); p++)
-        (*p)->detail()->set_color(gr_block_detail::WHITE);
+  // Mark all blocks as unvisited
+  for (gr_block_viter_t p = blocks.begin(); p != blocks.end(); p++)
+    (*p)->detail()->set_color(gr_block_detail::WHITE);
 
-    // Recursively mark all reachable blocks
-    reachable_dfs_visit(block, blocks);
+  // Recursively mark all reachable blocks
+  reachable_dfs_visit(block, blocks);
 
-    // Collect all the blocks that have been visited
-    for (gr_block_viter_t p = blocks.begin(); p != blocks.end(); p++)
-        if ((*p)->detail()->color() == gr_block_detail::BLACK)
-            result.push_back(*p);
+  // Collect all the blocks that have been visited
+  for (gr_block_viter_t p = blocks.begin(); p != blocks.end(); p++)
+    if ((*p)->detail()->color() == gr_block_detail::BLACK)
+      result.push_back(*p);
 
-    return result;
+  return result;
 }
 
 // Recursively mark all reachable blocks from given block and block list
 void 
 gr_simple_flowgraph_detail::reachable_dfs_visit(gr_block_sptr block, 
gr_block_vector_t &blocks)
 {
-    // Mark the current one as visited
-    block->detail()->set_color(gr_block_detail::BLACK);
+  // Mark the current one as visited
+  block->detail()->set_color(gr_block_detail::BLACK);
 
-    // Recurse into adjacent vertices
-    gr_block_vector_t adjacent = calc_adjacent_blocks(block, blocks);
+  // Recurse into adjacent vertices
+  gr_block_vector_t adjacent = calc_adjacent_blocks(block, blocks);
 
-    for (gr_block_viter_t p = adjacent.begin(); p != adjacent.end(); p++)
-        if ((*p)->detail()->color() == gr_block_detail::WHITE)
-               reachable_dfs_visit(*p, blocks);
+  for (gr_block_viter_t p = adjacent.begin(); p != adjacent.end(); p++)
+    if ((*p)->detail()->color() == gr_block_detail::WHITE)
+      reachable_dfs_visit(*p, blocks);
 }
 
 // Return a list of block adjacent to a given block along any edge
 gr_block_vector_t 
 gr_simple_flowgraph_detail::calc_adjacent_blocks(gr_block_sptr block, 
gr_block_vector_t &blocks)
 {
-    gr_block_vector_t tmp, result;
-    std::insert_iterator<gr_block_vector_t> inserter(result, result.begin());
+  gr_block_vector_t tmp, result;
+  std::insert_iterator<gr_block_vector_t> inserter(result, result.begin());
     
-    // Find any blocks that are inputs or outputs
-    for (gr_edge_viter_t p = d_edges.begin(); p != d_edges.end(); p++) {
-        if (lookup_block((*p)->src_name()) == block)
-            tmp.push_back(lookup_block((*p)->dst_name()));
-        if (lookup_block((*p)->dst_name()) == block)
-            tmp.push_back(lookup_block((*p)->src_name()));
-    }    
+  // Find any blocks that are inputs or outputs
+  for (gr_edge_viter_t p = d_edges.begin(); p != d_edges.end(); p++) {
 
-    // Remove duplicates
-    sort(tmp.begin(), tmp.end());
-    unique_copy(tmp.begin(), tmp.end(), inserter);
-    return result;
+    // Edges to "NC" are silently ignored
+    if ((*p)->src_name() == "NC" || (*p)->dst_name() == "NC")
+      continue;
+
+    if (lookup_block((*p)->src_name()) == block)
+      tmp.push_back(lookup_block((*p)->dst_name()));
+    if (lookup_block((*p)->dst_name()) == block)
+      tmp.push_back(lookup_block((*p)->src_name()));
+  }    
+
+  // Remove duplicates
+  sort(tmp.begin(), tmp.end());
+  unique_copy(tmp.begin(), tmp.end(), inserter);
+  return result;
 }
 
 gr_block_vector_t
 gr_simple_flowgraph_detail::topological_sort(gr_block_vector_t &blocks)
 {
-    gr_block_vector_t result, tmp;
-    tmp = sort_sources_first(blocks);
+  gr_block_vector_t result, tmp;
+  tmp = sort_sources_first(blocks);
 
-    // Start 'em all white
-    for (gr_block_viter_t p = tmp.begin(); p != tmp.end(); p++)
-        (*p)->detail()->set_color(gr_block_detail::WHITE);
+  // Start 'em all white
+  for (gr_block_viter_t p = tmp.begin(); p != tmp.end(); p++)
+    (*p)->detail()->set_color(gr_block_detail::WHITE);
 
-    for (gr_block_viter_t p = tmp.begin(); p != tmp.end(); p++) {
-        if ((*p)->detail()->color() == gr_block_detail::WHITE)
-            topological_dfs_visit(*p, result);
-    }    
+  for (gr_block_viter_t p = tmp.begin(); p != tmp.end(); p++) {
+    if ((*p)->detail()->color() == gr_block_detail::WHITE)
+      topological_dfs_visit(*p, result);
+  }    
 
-    reverse(result.begin(), result.end());
+  reverse(result.begin(), result.end());
 
-    return result;
+  return result;
 }
 
 bool
 gr_simple_flowgraph_detail::source_p(gr_block_sptr block)
 {
-    return (calc_upstream_edges(lookup_name(block)).size() == 0);
+  return (calc_upstream_edges(lookup_name(block)).size() == 0);
 }
 
 gr_block_vector_t
 gr_simple_flowgraph_detail::sort_sources_first(gr_block_vector_t &blocks)
 {
-    gr_block_vector_t sources, nonsources, result;
+  gr_block_vector_t sources, nonsources, result;
 
-    for (gr_block_viter_t p = blocks.begin(); p != blocks.end(); p++) {
-        if (source_p(*p))
-            sources.push_back(*p);
-        else
-            nonsources.push_back(*p);
-    }
+  for (gr_block_viter_t p = blocks.begin(); p != blocks.end(); p++) {
+    if (source_p(*p))
+      sources.push_back(*p);
+    else
+      nonsources.push_back(*p);
+  }
 
-    for (gr_block_viter_t p = sources.begin(); p != sources.end(); p++)
-        result.push_back(*p);
+  for (gr_block_viter_t p = sources.begin(); p != sources.end(); p++)
+    result.push_back(*p);
 
-    for (gr_block_viter_t p = nonsources.begin(); p != nonsources.end(); p++)
-        result.push_back(*p);
+  for (gr_block_viter_t p = nonsources.begin(); p != nonsources.end(); p++)
+    result.push_back(*p);
 
-    return result;
+  return result;
 }
 
 void
 gr_simple_flowgraph_detail::topological_dfs_visit(gr_block_sptr block, 
gr_block_vector_t &output)
 {
-    block->detail()->set_color(gr_block_detail::GREY);
+  block->detail()->set_color(gr_block_detail::GREY);
 
-    gr_block_vector_t blocks(calc_downstream_blocks(lookup_name(block)));
+  gr_block_vector_t blocks(calc_downstream_blocks(lookup_name(block)));
 
-    for (gr_block_viter_t p = blocks.begin(); p != blocks.end(); p++) {
-        switch ((*p)->detail()->color()) {
-            case gr_block_detail::WHITE:           
-                topological_dfs_visit(*p, output);
-                break;
+  for (gr_block_viter_t p = blocks.begin(); p != blocks.end(); p++) {
+    switch ((*p)->detail()->color()) {
+    case gr_block_detail::WHITE:           
+      topological_dfs_visit(*p, output);
+      break;
 
-            case gr_block_detail::GREY:            
-                throw std::runtime_error("flow graph has loops!");
+    case gr_block_detail::GREY:            
+      throw std::runtime_error("flow graph has loops!");
 
-            case gr_block_detail::BLACK:
-                continue;
+    case gr_block_detail::BLACK:
+      continue;
 
-            default:
-                throw std::runtime_error("invalid color on block!");
-        }
+    default:
+      throw std::runtime_error("invalid color on block!");
     }
+  }
 
-    block->detail()->set_color(gr_block_detail::BLACK);
-    output.push_back(block);
+  block->detail()->set_color(gr_block_detail::BLACK);
+  output.push_back(block);
 }
+
+void
+gr_simple_flowgraph_detail::merge_connections(gr_simple_flowgraph_sptr sfg)
+{
+  if (GR_SIMPLE_FLOWGRAPH_DETAIL_DEBUG)
+    std::cout << "merge_connections() hit" << std::endl;
+}

Modified: 
gnuradio/branches/developers/jcorgan/hier2/gnuradio-core/src/lib/runtime/gr_simple_flowgraph_detail.h
===================================================================
--- 
gnuradio/branches/developers/jcorgan/hier2/gnuradio-core/src/lib/runtime/gr_simple_flowgraph_detail.h
       2007-04-07 14:16:19 UTC (rev 4913)
+++ 
gnuradio/branches/developers/jcorgan/hier2/gnuradio-core/src/lib/runtime/gr_simple_flowgraph_detail.h
       2007-04-07 14:22:29 UTC (rev 4914)
@@ -1,6 +1,6 @@
 /* -*- c++ -*- */
 /*
- * Copyright 2006 Free Software Foundation, Inc.
+ * Copyright 2006,2007 Free Software Foundation, Inc.
  * 
  * This file is part of GNU Radio
  * 
@@ -25,6 +25,7 @@
 
 #include <gr_block.h>
 #include <map>
+#include <iostream>
 
 #define GR_FIXED_BUFFER_SIZE (32*(1L<<10))
 
@@ -34,13 +35,13 @@
 class gr_endpoint
 {
 private:
-    std::string d_name;
-    int d_port;
+  std::string d_name;
+  int d_port;
 
 public:
-    gr_endpoint(const std::string &name, int port) { d_name = name; d_port = 
port; }
-    const std::string &name() const { return d_name; }
-    int port() const { return d_port; }
+  gr_endpoint(const std::string &name, int port) { d_name = name; d_port = 
port; }
+  const std::string &name() const { return d_name; }
+  int port() const { return d_port; }
 };    
 
 class gr_edge;
@@ -51,20 +52,23 @@
 class gr_edge
 {
 private:
-    friend gr_edge_sptr gr_make_edge(const std::string &src_name, int src_port,
-                                     const std::string &dst_name, int 
dst_port);
-    gr_edge(const std::string &name, int src_port,
-            const std::string &name, int dst_port);
+  friend gr_edge_sptr gr_make_edge(const std::string &src_name, int src_port,
+                                  const std::string &dst_name, int dst_port);
+  gr_edge(const std::string &name, int src_port,
+         const std::string &name, int dst_port);
 
-    gr_endpoint d_src;
-    gr_endpoint d_dst;
+  gr_endpoint d_src;
+  gr_endpoint d_dst;
 
 public:
-    ~gr_edge();
-    const std::string src_name() const { return d_src.name(); }
-    const std::string dst_name() const { return d_dst.name(); }
-    int src_port() const { return d_src.port(); }
-    int dst_port() const { return d_dst.port(); }
+  ~gr_edge();
+
+  gr_endpoint src() const { return d_src; }
+  gr_endpoint dst() const { return d_dst; }
+  const std::string src_name() const { return d_src.name(); }
+  const std::string dst_name() const { return d_dst.name(); }
+  int src_port() const { return d_src.port(); }
+  int dst_port() const { return d_dst.port(); }
 };
 
 typedef std::vector<gr_edge_sptr> gr_edge_vector_t;
@@ -73,63 +77,80 @@
 class gr_simple_flowgraph_detail
 {
 private:
-    friend class gr_simple_flowgraph;
-    friend class gr_runtime_impl;
-    friend class topo_block_cmp;
+  friend class gr_simple_flowgraph;
+  friend class gr_runtime_impl;
+  friend class topo_block_cmp;
     
-    gr_simple_flowgraph_detail();
+  gr_simple_flowgraph_detail();
 
-    gr_component_map_t d_components;
-    gr_edge_vector_t   d_edges;
-    static const unsigned int s_fixed_buffer_size = GR_FIXED_BUFFER_SIZE;
+  gr_component_map_t d_components;
+  gr_edge_vector_t   d_edges;
+  static const unsigned int s_fixed_buffer_size = GR_FIXED_BUFFER_SIZE;
     
-    void reset();
-    void define_component(const std::string &name, gr_block_sptr block);    
-    void connect(const std::string &src, int src_port, 
-                 const std::string &dst, int dst_port);
-    gr_block_sptr lookup_block(const std::string &name);
-    std::string lookup_name(const gr_block_sptr block);
+  void reset();
+  void define_component(const std::string &name, gr_block_sptr block);    
+  void connect(const std::string &src, int src_port, 
+              const std::string &dst, int dst_port);
+  gr_block_sptr lookup_block(const std::string &name);
+  std::string lookup_name(const gr_block_sptr block);
 
-    void check_valid_port(gr_io_signature_sptr sig, int port);
-    void check_dst_not_used(const std::string &name, int port);
-    void check_type_match(gr_block_sptr src_block, int src_port,
-                          gr_block_sptr dst_block, int dst_port);
-    void validate();
-    gr_edge_vector_t calc_connections(const std::string &name, bool 
check_inputs); // false=use outputs
-    std::vector<int> calc_used_ports(const std::string &name, bool 
check_inputs); 
-    void check_contiguity(gr_block_sptr block, const std::vector<int> 
&used_ports, 
-                          bool check_inputs);
-    void setup_connections();
-    gr_buffer_sptr allocate_buffer(const std::string &name, int port);
-    gr_block_vector_t calc_downstream_blocks(const std::string &name, int 
port);
-    gr_block_vector_t calc_downstream_blocks(const std::string &name);
-    gr_edge_vector_t calc_upstream_edges(const std::string &name);
-    gr_block_vector_t calc_used_blocks();
-    std::vector<gr_block_vector_t> partition();
-    gr_block_vector_t calc_reachable_blocks(gr_block_sptr block, 
gr_block_vector_t &blocks);
-    gr_block_vector_t topological_sort(gr_block_vector_t &blocks);
-    void reachable_dfs_visit(gr_block_sptr block, gr_block_vector_t &blocks);
-    gr_block_vector_t calc_adjacent_blocks(gr_block_sptr block, 
gr_block_vector_t &blocks);
-    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 check_valid_port(gr_io_signature_sptr sig, int port);
+  void check_dst_not_used(const std::string &name, int port);
+  void check_type_match(gr_block_sptr src_block, int src_port,
+                       gr_block_sptr dst_block, int dst_port);
+  void validate();
+  gr_edge_vector_t calc_connections(const std::string &name, bool 
check_inputs); // false=use outputs
+  std::vector<int> calc_used_ports(const std::string &name, bool 
check_inputs); 
+  void check_contiguity(gr_block_sptr block, const std::vector<int> 
&used_ports, 
+                       bool check_inputs);
+  void setup_connections();
+  void merge_connections(gr_simple_flowgraph_sptr sfg);
+
+  gr_buffer_sptr allocate_buffer(const std::string &name, int port);
+  gr_block_vector_t calc_downstream_blocks(const std::string &name, int port);
+  gr_block_vector_t calc_downstream_blocks(const std::string &name);
+  gr_edge_vector_t calc_upstream_edges(const std::string &name);
+  gr_block_vector_t calc_used_blocks();
+  std::vector<gr_block_vector_t> partition();
+  gr_block_vector_t calc_reachable_blocks(gr_block_sptr block, 
gr_block_vector_t &blocks);
+  gr_block_vector_t topological_sort(gr_block_vector_t &blocks);
+  void reachable_dfs_visit(gr_block_sptr block, gr_block_vector_t &blocks);
+  gr_block_vector_t calc_adjacent_blocks(gr_block_sptr block, 
gr_block_vector_t &blocks);
+  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);
         
 public:
-    ~gr_simple_flowgraph_detail();
+  ~gr_simple_flowgraph_detail();
 };
 
 inline std::ostream&
 operator <<(std::ostream& os, const gr_block_sptr p)
 {
-    os << "<gr_block " << p->name() << " (" << p->unique_id() << ")>";
-    return os;
+  os << "<gr_block " << p->name() << " (" << p->unique_id() << ")>";
+  return os;
 }
 
 inline std::ostream&
 operator <<(std::ostream &os, const gr_endpoint endp)
 {
-    os << endp.name() << ":" << endp.port();
-    return os;
+  os << endp.name() << ":" << endp.port();
+  return os;
 }
 
+inline std::ostream&
+operator <<(std::ostream &os, const gr_edge_sptr edge)
+{
+  os << edge->src() << "->" << edge->dst();
+  return os;
+}
+
+inline void
+enumerate_edges(gr_edge_vector_t &edges)
+{
+  std::cout << "Edge list has " << edges.size() << " elements" << std::endl;
+  for(gr_edge_viter_t p = edges.begin(); p != edges.end(); p++)
+    std::cout << *p << std::endl;
+}
+
 #endif /* INCLUDED_GR_SIMPLE_FLOWGRAPH_H */

Modified: 
gnuradio/branches/developers/jcorgan/hier2/gnuradio-core/src/python/gnuradio/gr/hier_block2.py
===================================================================
--- 
gnuradio/branches/developers/jcorgan/hier2/gnuradio-core/src/python/gnuradio/gr/hier_block2.py
      2007-04-07 14:16:19 UTC (rev 4913)
+++ 
gnuradio/branches/developers/jcorgan/hier2/gnuradio-core/src/python/gnuradio/gr/hier_block2.py
      2007-04-07 14:22:29 UTC (rev 4914)
@@ -21,7 +21,7 @@
 
 from gnuradio_swig_python import hier_block2_swig, gr_make_runtime, \
     runtime_run_unlocked, runtime_start_unlocked, runtime_stop_unlocked, \
-    runtime_wait_unlocked 
+    runtime_wait_unlocked, runtime_restart_unlocked
 
 #
 # This hack forces a 'has-a' relationship to look like an 'is-a' one.
@@ -41,6 +41,10 @@
     def define_component(self, name, comp):
        return self._hb.define_component(name, comp.basic_block())
 
+# 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
+
 class runtime(object):
     def __init__(self, top_block):
         if (isinstance(top_block, hier_block2)):
@@ -59,3 +63,6 @@
 
     def wait(self):
         runtime_wait_unlocked(self._r)
+
+    def restart(self):
+        runtime_restart_unlocked(self._r)

Modified: 
gnuradio/branches/developers/jcorgan/hier2/gnuradio-core/src/python/gnuradio/gr/qa_hier_block2.py
===================================================================
--- 
gnuradio/branches/developers/jcorgan/hier2/gnuradio-core/src/python/gnuradio/gr/qa_hier_block2.py
   2007-04-07 14:16:19 UTC (rev 4913)
+++ 
gnuradio/branches/developers/jcorgan/hier2/gnuradio-core/src/python/gnuradio/gr/qa_hier_block2.py
   2007-04-07 14:22:29 UTC (rev 4914)
@@ -6,10 +6,10 @@
 
     def setUp(self):
        pass
-       
+
     def tearDown(self):
        pass
-       
+
     def test_001_make(self):
        hblock = gr.hier_block2("test_block", 
                                gr.io_signature(1,1,gr.sizeof_int), 
@@ -33,11 +33,22 @@
                                gr.io_signature(1,1,gr.sizeof_int))
        self.assertRaises(ValueError, 
            lambda: hblock.define_component("self", gr.nop(gr.sizeof_int)))
+        self.assertRaises(ValueError,
+            lambda: hblock.define_component("NC", gr.nop(gr.sizeof_int)))
 
-    def test_004_define_component_name_in_use(self):
+    def test_004_define_component_illegal_character(self):
        hblock = gr.hier_block2("test_block", 
                                gr.io_signature(1,1,gr.sizeof_int), 
                                gr.io_signature(1,1,gr.sizeof_int))
+       self.assertRaises(ValueError, 
+           lambda: hblock.define_component("nop.1", gr.nop(gr.sizeof_int)))
+        self.assertRaises(ValueError,
+            lambda: hblock.define_component("nop/1", gr.nop(gr.sizeof_int)))
+
+    def test_005_define_component_name_in_use(self):
+       hblock = gr.hier_block2("test_block", 
+                               gr.io_signature(1,1,gr.sizeof_int), 
+                               gr.io_signature(1,1,gr.sizeof_int))
        hblock.define_component("src", gr.null_source(gr.sizeof_int))
        self.assertRaises(ValueError, 
            lambda: hblock.define_component("src", gr.null_sink(gr.sizeof_int)))
@@ -72,7 +83,7 @@
        hblock.define_component("nop1", nop1)
        self.assertRaises(ValueError, 
            lambda: hblock.connect("nop2", 0, "self", 0))
-    
+
     def test_010_connect_unknown_dst(self):
        hblock = gr.hier_block2("test_block", 
                                gr.io_signature(1,1,gr.sizeof_int), 
@@ -96,7 +107,7 @@
        hblock.define_component("nop1", gr.nop(gr.sizeof_int))
        self.assertRaises(ValueError, 
            lambda: hblock.connect("self", 1, "nop1", 0))
-    
+
     def test_013_connect_invalid_dst_port_neg(self):
        hblock = gr.hier_block2("test_block", 
                                gr.io_signature(1,1,gr.sizeof_int), 
@@ -122,7 +133,7 @@
        hblock.connect("nop1", 0, "self", 0);
        self.assertRaises(ValueError, 
            lambda: hblock.connect("nop1", 0, "self", 0))
-    
+
     def test_016_connect_one_src_two_dst(self):
        hblock = gr.hier_block2("test_block", 
                                gr.io_signature(1,1,gr.sizeof_int), 
@@ -146,93 +157,85 @@
                                gr.io_signature(0,0,gr.sizeof_int), 
                                gr.io_signature(0,0,gr.sizeof_int))
        hblock.check_topology(0, 0);
-    """
-    def test_019_validate(self):
-       hblock = gr.hier_block2("test_block", 
-                               gr.io_signature(0,0,gr.sizeof_int), 
-                               gr.io_signature(0,0,gr.sizeof_int))
-       runtime = gr.runtime(hblock)
-       runtime.validate()
-    
-    def test_020_validate_1(self):
-       hblock = gr.hier_block2("test_block", 
-                               gr.io_signature(0,0,gr.sizeof_int), 
-                               gr.io_signature(0,0,gr.sizeof_int))
-       hblock.define_component("src", gr.null_source(gr.sizeof_int))
-       hblock.define_component("dst1", gr.null_sink(gr.sizeof_int))
-       hblock.define_component("dst2", gr.null_sink(gr.sizeof_int))
-       hblock.connect("src", 0, "dst1", 0)
-       hblock.connect("src", 0, "dst2", 0)                     
-       runtime = gr.runtime(hblock)
-       runtime.validate()
 
-    def test_021_validate_2(self):
+    def test_019_disconnect(self):
        hblock = gr.hier_block2("test_block", 
-                               gr.io_signature(0,0,gr.sizeof_int), 
-                               gr.io_signature(0,0,gr.sizeof_int))
-       hblock.define_component("src1", gr.null_source(gr.sizeof_int))
+                               gr.io_signature(1,1,gr.sizeof_int), 
+                               gr.io_signature(1,1,gr.sizeof_int))
        hblock.define_component("nop1", gr.nop(gr.sizeof_int))
-       hblock.define_component("dst1", gr.null_sink(gr.sizeof_int))
-       hblock.define_component("dst2", gr.null_sink(gr.sizeof_int))
-       hblock.connect("src1", 0, "nop1", 0)
-       hblock.connect("src1", 0, "nop1", 1)
-       hblock.connect("nop1", 0, "dst1", 0)
-       hblock.connect("nop1", 1, "dst2", 0)
-       runtime = gr.runtime(hblock)
-       runtime.validate()
-        
-    def test_022_validate_3(self):
+       hblock.define_component("nop2", gr.nop(gr.sizeof_int))
+       hblock.connect("nop1", 0, "nop2", 0)
+        hblock.disconnect("nop1", 0, "nop2", 0)
+
+    def test_020_disconnect_unknown(self):
        hblock = gr.hier_block2("test_block", 
-                               gr.io_signature(0,0,gr.sizeof_int), 
-                               gr.io_signature(0,0,gr.sizeof_int))
-       hblock.define_component("src1", gr.null_source(gr.sizeof_int))
+                               gr.io_signature(1,1,gr.sizeof_int), 
+                               gr.io_signature(1,1,gr.sizeof_int))
        hblock.define_component("nop1", gr.nop(gr.sizeof_int))
-       hblock.define_component("dst1", gr.null_sink(gr.sizeof_int))
-       hblock.define_component("dst2", gr.null_sink(gr.sizeof_int))
-       hblock.connect("src1", 0, "nop1", 0)
-       hblock.connect("src1", 0, "nop1", 2)
-       hblock.connect("nop1", 0, "dst1", 0)
-       hblock.connect("nop1", 1, "dst2", 0)
-       runtime = gr.runtime(hblock)
-       self.assertRaises(RuntimeError,
-           lambda: runtime.validate())
-        
-    def test_023_validate_4(self):
-       hblock = gr.hier_block2("test_block", 
-                               gr.io_signature(0,0,gr.sizeof_int), 
-                               gr.io_signature(0,0,gr.sizeof_int))
-       hblock.define_component("src1", gr.null_source(gr.sizeof_int))
-       hblock.define_component("nop1", gr.nop(gr.sizeof_int))
-       hblock.define_component("dst1", gr.null_sink(gr.sizeof_int))
-       hblock.define_component("dst2", gr.null_sink(gr.sizeof_int))
-       hblock.connect("src1", 0, "nop1", 0)
-       hblock.connect("src1", 0, "nop1", 1)
-       hblock.connect("nop1", 0, "dst1", 0)
-       hblock.connect("nop1", 2, "dst2", 0)
-       runtime = gr.runtime(hblock)
-       self.assertRaises(RuntimeError,
-           lambda: runtime.validate())
-        
-    def test_024_validate_5(self):
-       hblock = gr.hier_block2("test_block", 
-                               gr.io_signature(0,0,gr.sizeof_int), 
-                               gr.io_signature(0,0,gr.sizeof_int))
-       hblock.define_component("src1", gr.null_source(gr.sizeof_int))
-       hblock.define_component("nop1", gr.nop(gr.sizeof_int))
-       hblock.define_component("dst1", gr.null_sink(gr.sizeof_int))
-       hblock.define_component("dst2", gr.null_sink(gr.sizeof_int))
-       hblock.connect("src1", 0, "nop1", 0)
-       hblock.connect("src1", 0, "nop1", 1)
-       hblock.connect("nop1", 0, "dst1", 0)
-       hblock.connect("nop1", 1, "dst2", 0)
-       runtime = gr.runtime(hblock)
-       runtime.validate()
-       # Pending implementation of disconnect
-       # hblock.disconnect("src1", 0, "nop1", 1)
-       # runtime.validate()    
-       # self.assertRaises(ValueError,
-       #     lambda: hblock.disconnect("src1", 0, "nop1", 1))
-       """
-               
+       hblock.define_component("nop2", gr.nop(gr.sizeof_int))
+       hblock.connect("nop1", 0, "nop2", 0)
+       self.assertRaises(ValueError, 
+           lambda: hblock.disconnect("nop1", 0, "foo", 0))
+
+    def test_021_run(self):
+        expected = (1.0, 2.0, 3.0, 4.0)
+
+        hblock = gr.hier_block2("test_block",
+                                gr.io_signature(0,0,0),
+                                gr.io_signature(0,0,0))
+        hblock.define_component("src", gr.vector_source_f(expected, False))
+        sink1 = gr.vector_sink_f()
+        sink2 = gr.vector_sink_f()
+        hblock.define_component("sink1", sink1)
+        hblock.define_component("sink2", sink2)
+        hblock.connect("src", 0, "sink1", 0)
+        hblock.connect("src", 0, "sink2", 0)
+        runtime = gr.runtime(hblock)
+        runtime.run()
+        actual1 = sink1.data()
+        actual2 = sink2.data()
+        self.assertEquals(expected, actual1)
+        self.assertEquals(expected, actual2)
+
+    def test_022_connect_disconnect(self):
+        expected = (1.0, 2.0, 3.0, 4.0)
+        hblock = gr.hier_block2("test_block",
+                                gr.io_signature(0,0,0),
+                                gr.io_signature(0,0,0))
+        hblock.define_component("src", gr.vector_source_f(expected, False))
+        sink1 = gr.vector_sink_f()
+        sink2 = gr.vector_sink_f()
+        hblock.define_component("sink1", sink1)
+        hblock.define_component("sink2", sink2)
+        hblock.connect("src", 0, "sink1", 0)
+        hblock.connect("src", 0, "sink2", 0)
+        hblock.disconnect("src", 0, "sink2", 0)
+        hblock.connect("NC", 0, "sink2", 0)
+        runtime = gr.runtime(hblock)
+        runtime.run()
+
+    def test_023_run_and_disconnect(self):
+        expected = (1.0, 2.0, 3.0, 4.0)
+        hblock = gr.hier_block2("test_block",
+                                gr.io_signature(0,0,0),
+                                gr.io_signature(0,0,0))
+        hblock.define_component("src", gr.vector_source_f(expected, False))
+        sink1 = gr.vector_sink_f()
+        sink2 = gr.vector_sink_f()
+        hblock.define_component("sink1", sink1)
+        hblock.define_component("sink2", sink2)
+        hblock.connect("src", 0, "sink1", 0)
+        hblock.connect("src", 0, "sink2", 0)
+        runtime = gr.runtime(hblock)
+        runtime.start()
+        hblock.disconnect("src", 0, "sink2", 0)
+        hblock.connect("NC", 0, "sink2", 0)
+        runtime.restart()
+        runtime.wait()
+        actual1 = sink1.data()
+        actual2 = sink2.data()
+        self.assertEquals(expected, actual1)
+        self.assertEquals((), actual2)
+
 if __name__ == "__main__":
     gr_unittest.main()





reply via email to

[Prev in Thread] Current Thread [Next in Thread]