From f561a45ce55debd0662ea38e17b2ea4ad50ad771 Mon Sep 17 00:00:00 2001 From: jcorgan Date: Thu, 23 Aug 2007 18:46:20 +0000 Subject: Merge r6160:6168 from jcorgan/fg into trunk. Refactors gr_simple_flowgraph into gr_flowgraph and gr_flat_flowgraph. Adds cppunit-based QA. Trial fix for ticket:164 included for free. git-svn-id: http://gnuradio.org/svn/gnuradio/trunk@6169 221aa14e-8319-0410-a670-987f0aec2ac5 --- gnuradio-core/src/lib/runtime/gr_flowgraph.cc | 436 ++++++++++++++++++++++++++ 1 file changed, 436 insertions(+) create mode 100644 gnuradio-core/src/lib/runtime/gr_flowgraph.cc (limited to 'gnuradio-core/src/lib/runtime/gr_flowgraph.cc') diff --git a/gnuradio-core/src/lib/runtime/gr_flowgraph.cc b/gnuradio-core/src/lib/runtime/gr_flowgraph.cc new file mode 100644 index 000000000..8e96dba75 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_flowgraph.cc @@ -0,0 +1,436 @@ +/* -*- 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 +#include +#include +#include + +#define GR_FLOWGRAPH_DEBUG 0 + +gr_edge::~gr_edge() +{ +} + +gr_flowgraph_sptr gr_make_flowgraph() +{ + return gr_flowgraph_sptr(new gr_flowgraph()); +} + +gr_flowgraph::gr_flowgraph() +{ +} + +gr_flowgraph::~gr_flowgraph() +{ +} + +void +gr_flowgraph::connect(const gr_endpoint &src, const gr_endpoint &dst) +{ + check_valid_port(src.block()->output_signature(), src.port()); + check_valid_port(dst.block()->input_signature(), dst.port()); + check_dst_not_used(dst); + check_type_match(src, dst); + + // All ist klar, Herr Kommisar + d_edges.push_back(gr_edge(src,dst)); +} + +void +gr_flowgraph::disconnect(const gr_endpoint &src, const gr_endpoint &dst) +{ + for (gr_edge_viter_t p = d_edges.begin(); p != d_edges.end(); p++) { + if (src == p->src() && dst == p->dst()) { + d_edges.erase(p); + return; + } + } + + throw std::invalid_argument("edge to disconnect not found"); +} + +void +gr_flowgraph::validate() +{ + d_blocks = calc_used_blocks(); + + for (gr_basic_block_viter_t p = d_blocks.begin(); p != d_blocks.end(); p++) { + std::vector used_ports; + int ninputs, noutputs; + + if (GR_FLOWGRAPH_DEBUG) + std::cout << "Validating block: " << (*p) << std::endl; + + used_ports = calc_used_ports(*p, true); // inputs + ninputs = used_ports.size(); + check_contiguity(*p, used_ports, true); // inputs + + used_ports = calc_used_ports(*p, false); // outputs + noutputs = used_ports.size(); + check_contiguity(*p, used_ports, false); // outputs + + if (!((*p)->check_topology(ninputs, noutputs))) + throw std::runtime_error("check topology failed"); + } +} + +void +gr_flowgraph::clear() +{ + // Boost shared pointers will deallocate as needed + d_blocks.clear(); + d_edges.clear(); +} + +void +gr_flowgraph::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"); +} + +void +gr_flowgraph::check_dst_not_used(const gr_endpoint &dst) +{ + // A destination is in use if it is already on the edge list + for (gr_edge_viter_t p = d_edges.begin(); p != d_edges.end(); p++) + if (p->dst() == dst) + throw std::invalid_argument("dst already in use"); +} + +void +gr_flowgraph::check_type_match(const gr_endpoint &src, const gr_endpoint &dst) +{ + 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("itemsize mismatch between src and dst"); +} + +gr_basic_block_vector_t +gr_flowgraph::calc_used_blocks() +{ + gr_basic_block_vector_t tmp, result; + std::insert_iterator inserter(result, result.begin()); + + // Collect all blocks in the edge list + for (gr_edge_viter_t p = d_edges.begin(); p != d_edges.end(); p++) { + tmp.push_back(p->src().block()); + tmp.push_back(p->dst().block()); + } + + // Return vector of unique blocks + sort(tmp.begin(), tmp.end()); + unique_copy(tmp.begin(), tmp.end(), inserter); + return result; +} + +std::vector +gr_flowgraph::calc_used_ports(gr_basic_block_sptr block, bool check_inputs) +{ + std::vector tmp, result; + std::insert_iterator > inserter(result, result.begin()); + + // Collect all seen ports + gr_edge_vector_t edges = calc_connections(block, 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()); + } + + // Return vector of unique values + std::sort(tmp.begin(), tmp.end()); + std::unique_copy(tmp.begin(), tmp.end(), inserter); + return result; +} + +gr_edge_vector_t +gr_flowgraph::calc_connections(gr_basic_block_sptr block, bool check_inputs) +{ + 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().block() == block) + result.push_back(*p); + } + else { + if (p->src().block() == block) + result.push_back(*p); + } + } + + return result; // assumes no duplicates +} + +void +gr_flowgraph::check_contiguity(gr_basic_block_sptr block, + const std::vector &used_ports, + bool check_inputs) +{ + gr_io_signature_sptr sig = + check_inputs ? block->input_signature() : block->output_signature(); + + int nports = used_ports.size(); + int min_ports = sig->min_streams(); + + if (nports == 0) { + if (min_ports == 0) + return; + else + 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) + throw std::runtime_error("missing input assignment"); + } +} + +gr_basic_block_vector_t +gr_flowgraph::calc_downstream_blocks(gr_basic_block_sptr block, int port) +{ + gr_basic_block_vector_t tmp, result; + std::insert_iterator inserter(result, result.begin()); + + for (gr_edge_viter_t p = d_edges.begin(); p != d_edges.end(); p++) + if (p->src() == gr_endpoint(block, port)) + tmp.push_back(p->dst().block()); + + // Remove duplicates + sort(tmp.begin(), tmp.end()); + unique_copy(tmp.begin(), tmp.end(), inserter); + return result; +} + +gr_basic_block_vector_t +gr_flowgraph::calc_downstream_blocks(gr_basic_block_sptr block) +{ + gr_basic_block_vector_t tmp, result; + std::insert_iterator inserter(result, result.begin()); + + for (gr_edge_viter_t p = d_edges.begin(); p != d_edges.end(); p++) + if (p->src().block() == block) + tmp.push_back(p->dst().block()); + + // Remove duplicates + sort(tmp.begin(), tmp.end()); + unique_copy(tmp.begin(), tmp.end(), inserter); + return result; +} + +gr_edge_vector_t +gr_flowgraph::calc_upstream_edges(gr_basic_block_sptr block) +{ + gr_edge_vector_t result; + + for (gr_edge_viter_t p = d_edges.begin(); p != d_edges.end(); p++) + if (p->dst().block() == block) + result.push_back(*p); + + return result; // Assume no duplicates +} + +bool +gr_flowgraph::has_block_p(gr_basic_block_sptr block) +{ + gr_basic_block_viter_t result; + result = std::find(d_blocks.begin(), d_blocks.end(), block); + return (result != d_blocks.end()); +} + +gr_edge +gr_flowgraph::calc_upstream_edge(gr_basic_block_sptr block, int port) +{ + gr_edge result; + + for (gr_edge_viter_t p = d_edges.begin(); p != d_edges.end(); p++) { + if (p->dst() == gr_endpoint(block, port)) { + result = (*p); + break; + } + } + + return result; +} + +std::vector +gr_flowgraph::partition() +{ + std::vector result; + gr_basic_block_vector_t blocks = calc_used_blocks(); + gr_basic_block_vector_t graph; + + while (blocks.size() > 0) { + graph = calc_reachable_blocks(blocks[0], blocks); + assert(graph.size()); + result.push_back(topological_sort(graph)); + + for (gr_basic_block_viter_t p = graph.begin(); p != graph.end(); p++) + blocks.erase(find(blocks.begin(), blocks.end(), *p)); + } + + return result; +} + +gr_basic_block_vector_t +gr_flowgraph::calc_reachable_blocks(gr_basic_block_sptr block, gr_basic_block_vector_t &blocks) +{ + gr_basic_block_vector_t result; + + // Mark all blocks as unvisited + for (gr_basic_block_viter_t p = blocks.begin(); p != blocks.end(); p++) + (*p)->set_color(gr_basic_block::WHITE); + + // Recursively mark all reachable blocks + reachable_dfs_visit(block, blocks); + + // Collect all the blocks that have been visited + for (gr_basic_block_viter_t p = blocks.begin(); p != blocks.end(); p++) + if ((*p)->color() == gr_basic_block::BLACK) + result.push_back(*p); + + return result; +} + +// Recursively mark all reachable blocks from given block and block list +void +gr_flowgraph::reachable_dfs_visit(gr_basic_block_sptr block, gr_basic_block_vector_t &blocks) +{ + // Mark the current one as visited + block->set_color(gr_basic_block::BLACK); + + // Recurse into adjacent vertices + gr_basic_block_vector_t adjacent = calc_adjacent_blocks(block, blocks); + + for (gr_basic_block_viter_t p = adjacent.begin(); p != adjacent.end(); p++) + if ((*p)->color() == gr_basic_block::WHITE) + reachable_dfs_visit(*p, blocks); +} + +// Return a list of block adjacent to a given block along any edge +gr_basic_block_vector_t +gr_flowgraph::calc_adjacent_blocks(gr_basic_block_sptr block, gr_basic_block_vector_t &blocks) +{ + gr_basic_block_vector_t tmp, result; + std::insert_iterator 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 (p->src().block() == block) + tmp.push_back(p->dst().block()); + if (p->dst().block() == block) + tmp.push_back(p->src().block()); + } + + // Remove duplicates + sort(tmp.begin(), tmp.end()); + unique_copy(tmp.begin(), tmp.end(), inserter); + return result; +} + +gr_basic_block_vector_t +gr_flowgraph::topological_sort(gr_basic_block_vector_t &blocks) +{ + gr_basic_block_vector_t tmp; + gr_basic_block_vector_t result; + tmp = sort_sources_first(blocks); + + // Start 'em all white + for (gr_basic_block_viter_t p = tmp.begin(); p != tmp.end(); p++) + (*p)->set_color(gr_basic_block::WHITE); + + for (gr_basic_block_viter_t p = tmp.begin(); p != tmp.end(); p++) { + if ((*p)->color() == gr_basic_block::WHITE) + topological_dfs_visit(*p, result); + } + + reverse(result.begin(), result.end()); + return result; +} + +gr_basic_block_vector_t +gr_flowgraph::sort_sources_first(gr_basic_block_vector_t &blocks) +{ + gr_basic_block_vector_t sources, nonsources, result; + + for (gr_basic_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_basic_block_viter_t p = sources.begin(); p != sources.end(); p++) + result.push_back(*p); + + for (gr_basic_block_viter_t p = nonsources.begin(); p != nonsources.end(); p++) + result.push_back(*p); + + return result; +} + +bool +gr_flowgraph::source_p(gr_basic_block_sptr block) +{ + return (calc_upstream_edges(block).size() == 0); +} + +void +gr_flowgraph::topological_dfs_visit(gr_basic_block_sptr block, gr_basic_block_vector_t &output) +{ + block->set_color(gr_basic_block::GREY); + gr_basic_block_vector_t blocks(calc_downstream_blocks(block)); + + for (gr_basic_block_viter_t p = blocks.begin(); p != blocks.end(); p++) { + switch ((*p)->color()) { + case gr_basic_block::WHITE: + topological_dfs_visit(*p, output); + break; + + case gr_basic_block::GREY: + throw std::runtime_error("flow graph has loops!"); + + case gr_basic_block::BLACK: + continue; + + default: + throw std::runtime_error("invalid color on block!"); + } + } + + block->set_color(gr_basic_block::BLACK); + output.push_back(block); +} + -- cgit From 0786370660817056e2ecb6b9793894678445a1a8 Mon Sep 17 00:00:00 2001 From: jcorgan Date: Wed, 29 Aug 2007 19:03:41 +0000 Subject: Fixes ticket:172 and ticket:174 git-svn-id: http://gnuradio.org/svn/gnuradio/trunk@6207 221aa14e-8319-0410-a670-987f0aec2ac5 --- gnuradio-core/src/lib/runtime/gr_flowgraph.cc | 71 ++++++++++++++++++++------- 1 file changed, 54 insertions(+), 17 deletions(-) (limited to 'gnuradio-core/src/lib/runtime/gr_flowgraph.cc') diff --git a/gnuradio-core/src/lib/runtime/gr_flowgraph.cc b/gnuradio-core/src/lib/runtime/gr_flowgraph.cc index 8e96dba75..f4879f085 100644 --- a/gnuradio-core/src/lib/runtime/gr_flowgraph.cc +++ b/gnuradio-core/src/lib/runtime/gr_flowgraph.cc @@ -27,7 +27,7 @@ #include #include #include -#include +#include #define GR_FLOWGRAPH_DEBUG 0 @@ -70,7 +70,9 @@ gr_flowgraph::disconnect(const gr_endpoint &src, const gr_endpoint &dst) } } - throw std::invalid_argument("edge to disconnect not found"); + std::stringstream msg; + msg << "cannot disconnect edge " << gr_edge(src, dst) << ", not found"; + throw std::invalid_argument(msg.str()); } void @@ -93,8 +95,13 @@ gr_flowgraph::validate() noutputs = used_ports.size(); check_contiguity(*p, used_ports, false); // outputs - if (!((*p)->check_topology(ninputs, noutputs))) - throw std::runtime_error("check topology failed"); + if (!((*p)->check_topology(ninputs, noutputs))) { + std::stringstream msg; + msg << "check topology failed on " << (*p) + << " using ninputs=" << ninputs + << ", noutputs=" << noutputs; + throw std::runtime_error(msg.str()); + } } } @@ -109,10 +116,22 @@ gr_flowgraph::clear() void gr_flowgraph::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"); + std::stringstream msg; + + if (port < 0) { + msg << "negative port number " << port << " is invalid"; + throw std::invalid_argument(msg.str()); + } + + int max = sig->max_streams(); + if (max >= 0 && port >= max) { + msg << "port number " << port << " exceeds max of "; + if (max == 0) + msg << "(none)"; + else + msg << max-1; + throw std::invalid_argument(msg.str()); + } } void @@ -120,8 +139,11 @@ gr_flowgraph::check_dst_not_used(const gr_endpoint &dst) { // A destination is in use if it is already on the edge list for (gr_edge_viter_t p = d_edges.begin(); p != d_edges.end(); p++) - if (p->dst() == dst) - throw std::invalid_argument("dst already in use"); + if (p->dst() == dst) { + std::stringstream msg; + msg << "destination already in use by edge " << (*p); + throw std::invalid_argument(msg.str()); + } } void @@ -130,8 +152,12 @@ gr_flowgraph::check_type_match(const gr_endpoint &src, const gr_endpoint &dst) 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("itemsize mismatch between src and dst"); + if (src_size != dst_size) { + std::stringstream msg; + msg << "itemsize mismatch: " << src << " using " << src_size + << ", " << dst << " using " << dst_size; + throw std::invalid_argument(msg.str()); + } } gr_basic_block_vector_t @@ -197,6 +223,8 @@ gr_flowgraph::check_contiguity(gr_basic_block_sptr block, const std::vector &used_ports, bool check_inputs) { + std::stringstream msg; + gr_io_signature_sptr sig = check_inputs ? block->input_signature() : block->output_signature(); @@ -206,14 +234,23 @@ gr_flowgraph::check_contiguity(gr_basic_block_sptr block, if (nports == 0) { if (min_ports == 0) return; - else - throw std::runtime_error("insufficient ports"); + else { + msg << block << ": insufficient connected " + << (check_inputs ? "input ports " : "output ports ") + << "(" << min_ports+1 << " needed, " << nports+1 << " connected)"; + throw std::runtime_error(msg.str()); + } } if (used_ports[nports-1]+1 != nports) { - for (int i = 0; i < nports; i++) - if (used_ports[i] != i) - throw std::runtime_error("missing input assignment"); + for (int i = 0; i < nports; i++) { + if (used_ports[i] != i) { + msg << block << ": missing connection " + << (check_inputs ? "to input port " : "from output port ") + << i; + throw std::runtime_error(msg.str()); + } + } } } -- cgit From b0245c71f07edd7921f0b70d9050781b5cb0c4b2 Mon Sep 17 00:00:00 2001 From: jcorgan Date: Sun, 24 Feb 2008 01:54:50 +0000 Subject: Fix topology checking code in gr_flowgraph. Thanks to Dan Halperin. git-svn-id: http://gnuradio.org/svn/gnuradio/trunk@7802 221aa14e-8319-0410-a670-987f0aec2ac5 --- gnuradio-core/src/lib/runtime/gr_flowgraph.cc | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) (limited to 'gnuradio-core/src/lib/runtime/gr_flowgraph.cc') diff --git a/gnuradio-core/src/lib/runtime/gr_flowgraph.cc b/gnuradio-core/src/lib/runtime/gr_flowgraph.cc index f4879f085..359570347 100644 --- a/gnuradio-core/src/lib/runtime/gr_flowgraph.cc +++ b/gnuradio-core/src/lib/runtime/gr_flowgraph.cc @@ -124,7 +124,7 @@ gr_flowgraph::check_valid_port(gr_io_signature_sptr sig, int port) } int max = sig->max_streams(); - if (max >= 0 && port >= max) { + if (max != gr_io_signature::IO_INFINITE && port >= max) { msg << "port number " << port << " exceeds max of "; if (max == 0) msg << "(none)"; @@ -230,16 +230,23 @@ gr_flowgraph::check_contiguity(gr_basic_block_sptr block, int nports = used_ports.size(); int min_ports = sig->min_streams(); + int max_ports = sig->max_streams(); - if (nports == 0) { - if (min_ports == 0) - return; - else { - msg << block << ": insufficient connected " - << (check_inputs ? "input ports " : "output ports ") - << "(" << min_ports+1 << " needed, " << nports+1 << " connected)"; - throw std::runtime_error(msg.str()); - } + if (nports == 0 && min_ports == 0) + return; + + if (nports < min_ports) { + msg << block << ": insufficient connected " + << (check_inputs ? "input ports " : "output ports ") + << "(" << min_ports << " needed, " << nports << " connected)"; + throw std::runtime_error(msg.str()); + } + + if (nports > max_ports && max_ports != gr_io_signature::IO_INFINITE) { + msg << block << ": too many connected " + << (check_inputs ? "input ports " : "output ports ") + << "(" << max_ports << " allowed, " << nports << " connected)"; + throw std::runtime_error(msg.str()); } if (used_ports[nports-1]+1 != nports) { -- cgit From 5b09804605cd41bbc3fdcb917eda3f69a7598af9 Mon Sep 17 00:00:00 2001 From: jcorgan Date: Tue, 12 Aug 2008 17:38:29 +0000 Subject: Refactored unique vector functionality into template. git-svn-id: http://gnuradio.org/svn/gnuradio/trunk@9253 221aa14e-8319-0410-a670-987f0aec2ac5 --- gnuradio-core/src/lib/runtime/gr_flowgraph.cc | 55 ++++++++++++--------------- 1 file changed, 24 insertions(+), 31 deletions(-) (limited to 'gnuradio-core/src/lib/runtime/gr_flowgraph.cc') diff --git a/gnuradio-core/src/lib/runtime/gr_flowgraph.cc b/gnuradio-core/src/lib/runtime/gr_flowgraph.cc index 359570347..27f6257cc 100644 --- a/gnuradio-core/src/lib/runtime/gr_flowgraph.cc +++ b/gnuradio-core/src/lib/runtime/gr_flowgraph.cc @@ -48,6 +48,20 @@ gr_flowgraph::~gr_flowgraph() { } +// FIXME: move to libgruel as a utility function +template +static +std::vector +unique_vector(std::vector v) +{ + std::vector result; + std::insert_iterator > inserter(result, result.begin()); + + sort(v.begin(), v.end()); + unique_copy(v.begin(), v.end(), inserter); + return result; +} + void gr_flowgraph::connect(const gr_endpoint &src, const gr_endpoint &dst) { @@ -163,8 +177,7 @@ gr_flowgraph::check_type_match(const gr_endpoint &src, const gr_endpoint &dst) gr_basic_block_vector_t gr_flowgraph::calc_used_blocks() { - gr_basic_block_vector_t tmp, result; - std::insert_iterator inserter(result, result.begin()); + gr_basic_block_vector_t tmp; // Collect all blocks in the edge list for (gr_edge_viter_t p = d_edges.begin(); p != d_edges.end(); p++) { @@ -172,17 +185,13 @@ gr_flowgraph::calc_used_blocks() tmp.push_back(p->dst().block()); } - // Return vector of unique blocks - sort(tmp.begin(), tmp.end()); - unique_copy(tmp.begin(), tmp.end(), inserter); - return result; + return unique_vector(tmp); } std::vector gr_flowgraph::calc_used_ports(gr_basic_block_sptr block, bool check_inputs) { - std::vector tmp, result; - std::insert_iterator > inserter(result, result.begin()); + std::vector tmp; // Collect all seen ports gr_edge_vector_t edges = calc_connections(block, check_inputs); @@ -193,10 +202,7 @@ gr_flowgraph::calc_used_ports(gr_basic_block_sptr block, bool check_inputs) tmp.push_back(p->src().port()); } - // Return vector of unique values - std::sort(tmp.begin(), tmp.end()); - std::unique_copy(tmp.begin(), tmp.end(), inserter); - return result; + return unique_vector(tmp); } gr_edge_vector_t @@ -264,33 +270,25 @@ gr_flowgraph::check_contiguity(gr_basic_block_sptr block, gr_basic_block_vector_t gr_flowgraph::calc_downstream_blocks(gr_basic_block_sptr block, int port) { - gr_basic_block_vector_t tmp, result; - std::insert_iterator inserter(result, result.begin()); + gr_basic_block_vector_t tmp; for (gr_edge_viter_t p = d_edges.begin(); p != d_edges.end(); p++) if (p->src() == gr_endpoint(block, port)) tmp.push_back(p->dst().block()); - // Remove duplicates - sort(tmp.begin(), tmp.end()); - unique_copy(tmp.begin(), tmp.end(), inserter); - return result; + return unique_vector(tmp); } gr_basic_block_vector_t gr_flowgraph::calc_downstream_blocks(gr_basic_block_sptr block) { - gr_basic_block_vector_t tmp, result; - std::insert_iterator inserter(result, result.begin()); + gr_basic_block_vector_t tmp; for (gr_edge_viter_t p = d_edges.begin(); p != d_edges.end(); p++) if (p->src().block() == block) tmp.push_back(p->dst().block()); - // Remove duplicates - sort(tmp.begin(), tmp.end()); - unique_copy(tmp.begin(), tmp.end(), inserter); - return result; + return unique_vector(tmp); } gr_edge_vector_t @@ -386,22 +384,17 @@ gr_flowgraph::reachable_dfs_visit(gr_basic_block_sptr block, gr_basic_block_vect gr_basic_block_vector_t gr_flowgraph::calc_adjacent_blocks(gr_basic_block_sptr block, gr_basic_block_vector_t &blocks) { - gr_basic_block_vector_t tmp, result; - std::insert_iterator inserter(result, result.begin()); + gr_basic_block_vector_t tmp; // Find any blocks that are inputs or outputs for (gr_edge_viter_t p = d_edges.begin(); p != d_edges.end(); p++) { - if (p->src().block() == block) tmp.push_back(p->dst().block()); if (p->dst().block() == block) tmp.push_back(p->src().block()); } - // Remove duplicates - sort(tmp.begin(), tmp.end()); - unique_copy(tmp.begin(), tmp.end(), inserter); - return result; + return unique_vector(tmp); } gr_basic_block_vector_t -- cgit From aedfa8ec254f1def125167a77a50bb0eec4ab00c Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Mon, 24 Jan 2011 12:23:58 -0800 Subject: gr_flowgraph.cc explicit include of Added explicit include of , which was implicitly included by . Affects platforms where vector does not automatically pull in iterator. --- gnuradio-core/src/lib/runtime/gr_flowgraph.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'gnuradio-core/src/lib/runtime/gr_flowgraph.cc') diff --git a/gnuradio-core/src/lib/runtime/gr_flowgraph.cc b/gnuradio-core/src/lib/runtime/gr_flowgraph.cc index 27f6257cc..0d3bbb011 100644 --- a/gnuradio-core/src/lib/runtime/gr_flowgraph.cc +++ b/gnuradio-core/src/lib/runtime/gr_flowgraph.cc @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2007 Free Software Foundation, Inc. + * Copyright 2007,2011 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -28,6 +28,7 @@ #include #include #include +#include #define GR_FLOWGRAPH_DEBUG 0 -- cgit From f919f9dcbb54a08e6e26d6c229ce92fb784fa1b2 Mon Sep 17 00:00:00 2001 From: Tom Rondeau Date: Fri, 13 Apr 2012 18:36:53 -0400 Subject: Removed whitespace and added dtools/bin/remove-whitespace as a tool to do this in the future. The sed script was provided by Moritz Fischer. --- gnuradio-core/src/lib/runtime/gr_flowgraph.cc | 32 +++++++++++++-------------- 1 file changed, 16 insertions(+), 16 deletions(-) (limited to 'gnuradio-core/src/lib/runtime/gr_flowgraph.cc') diff --git a/gnuradio-core/src/lib/runtime/gr_flowgraph.cc b/gnuradio-core/src/lib/runtime/gr_flowgraph.cc index 0d3bbb011..78e1bc99a 100644 --- a/gnuradio-core/src/lib/runtime/gr_flowgraph.cc +++ b/gnuradio-core/src/lib/runtime/gr_flowgraph.cc @@ -1,19 +1,19 @@ /* -*- c++ -*- */ /* * Copyright 2007,2011 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, @@ -44,7 +44,7 @@ gr_flowgraph_sptr gr_make_flowgraph() gr_flowgraph::gr_flowgraph() { } - + gr_flowgraph::~gr_flowgraph() { } @@ -57,7 +57,7 @@ unique_vector(std::vector v) { std::vector result; std::insert_iterator > inserter(result, result.begin()); - + sort(v.begin(), v.end()); unique_copy(v.begin(), v.end(), inserter); return result; @@ -113,7 +113,7 @@ gr_flowgraph::validate() if (!((*p)->check_topology(ninputs, noutputs))) { std::stringstream msg; msg << "check topology failed on " << (*p) - << " using ninputs=" << ninputs + << " using ninputs=" << ninputs << ", noutputs=" << noutputs; throw std::runtime_error(msg.str()); } @@ -194,7 +194,7 @@ gr_flowgraph::calc_used_ports(gr_basic_block_sptr block, bool check_inputs) { std::vector tmp; - // Collect all seen ports + // Collect all seen ports gr_edge_vector_t edges = calc_connections(block, check_inputs); for (gr_edge_viter_t p = edges.begin(); p != edges.end(); p++) { if (check_inputs == true) @@ -259,7 +259,7 @@ gr_flowgraph::check_contiguity(gr_basic_block_sptr block, if (used_ports[nports-1]+1 != nports) { for (int i = 0; i < nports; i++) { if (used_ports[i] != i) { - msg << block << ": missing connection " + msg << block << ": missing connection " << (check_inputs ? "to input port " : "from output port ") << i; throw std::runtime_error(msg.str()); @@ -367,7 +367,7 @@ gr_flowgraph::calc_reachable_blocks(gr_basic_block_sptr block, gr_basic_block_ve } // Recursively mark all reachable blocks from given block and block list -void +void gr_flowgraph::reachable_dfs_visit(gr_basic_block_sptr block, gr_basic_block_vector_t &blocks) { // Mark the current one as visited @@ -382,18 +382,18 @@ gr_flowgraph::reachable_dfs_visit(gr_basic_block_sptr block, gr_basic_block_vect } // Return a list of block adjacent to a given block along any edge -gr_basic_block_vector_t +gr_basic_block_vector_t gr_flowgraph::calc_adjacent_blocks(gr_basic_block_sptr block, gr_basic_block_vector_t &blocks) { gr_basic_block_vector_t tmp; - + // Find any blocks that are inputs or outputs for (gr_edge_viter_t p = d_edges.begin(); p != d_edges.end(); p++) { if (p->src().block() == block) tmp.push_back(p->dst().block()); if (p->dst().block() == block) tmp.push_back(p->src().block()); - } + } return unique_vector(tmp); } @@ -412,7 +412,7 @@ gr_flowgraph::topological_sort(gr_basic_block_vector_t &blocks) for (gr_basic_block_viter_t p = tmp.begin(); p != tmp.end(); p++) { if ((*p)->color() == gr_basic_block::WHITE) topological_dfs_visit(*p, result); - } + } reverse(result.begin(), result.end()); return result; @@ -453,11 +453,11 @@ gr_flowgraph::topological_dfs_visit(gr_basic_block_sptr block, gr_basic_block_ve for (gr_basic_block_viter_t p = blocks.begin(); p != blocks.end(); p++) { switch ((*p)->color()) { - case gr_basic_block::WHITE: + case gr_basic_block::WHITE: topological_dfs_visit(*p, output); break; - case gr_basic_block::GREY: + case gr_basic_block::GREY: throw std::runtime_error("flow graph has loops!"); case gr_basic_block::BLACK: -- cgit From 6cc818260128df57c51a41e4e6aa459de5faf4fe Mon Sep 17 00:00:00 2001 From: Tim O'Shea Date: Fri, 30 Nov 2012 22:31:43 -0800 Subject: core: gr_blocks can now have only message ports with no general_work() * msg only blocks now get thread context * added blocking msg queue delete call * added gr_message_strobe block * added grc definitions for message_debug, message_strobe, pdu_to_tagged_stream, tagged_stream_to_pdu. * allow message fan-in connections in GRC --- gnuradio-core/src/lib/runtime/gr_flowgraph.cc | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'gnuradio-core/src/lib/runtime/gr_flowgraph.cc') diff --git a/gnuradio-core/src/lib/runtime/gr_flowgraph.cc b/gnuradio-core/src/lib/runtime/gr_flowgraph.cc index 78e1bc99a..69c304a3d 100644 --- a/gnuradio-core/src/lib/runtime/gr_flowgraph.cc +++ b/gnuradio-core/src/lib/runtime/gr_flowgraph.cc @@ -180,6 +180,11 @@ gr_flowgraph::calc_used_blocks() { gr_basic_block_vector_t tmp; + // make sure free standing message blocks are included + for (gr_basic_block_vector_t::iterator it=d_msgblocks.begin(); it!=d_msgblocks.end(); it++){ + tmp.push_back(*it); + } + // Collect all blocks in the edge list for (gr_edge_viter_t p = d_edges.begin(); p != d_edges.end(); p++) { tmp.push_back(p->src().block()); @@ -472,3 +477,7 @@ gr_flowgraph::topological_dfs_visit(gr_basic_block_sptr block, gr_basic_block_ve output.push_back(block); } +void gr_flowgraph::add_msg_block(gr_basic_block_sptr blk){ + d_msgblocks.push_back(blk); +} + -- cgit From 52ca5e2765b7a4532d26502b5b76b7c85c5019d7 Mon Sep 17 00:00:00 2001 From: Tim O'Shea Date: Fri, 7 Dec 2012 09:28:41 -0800 Subject: core: added gr_tuntap_pdu, gr_socket_pdu, and msg passing enhancements --- gnuradio-core/src/lib/runtime/gr_flowgraph.cc | 40 ++++++++++++++++++++++++--- 1 file changed, 36 insertions(+), 4 deletions(-) (limited to 'gnuradio-core/src/lib/runtime/gr_flowgraph.cc') diff --git a/gnuradio-core/src/lib/runtime/gr_flowgraph.cc b/gnuradio-core/src/lib/runtime/gr_flowgraph.cc index 69c304a3d..63a208480 100644 --- a/gnuradio-core/src/lib/runtime/gr_flowgraph.cc +++ b/gnuradio-core/src/lib/runtime/gr_flowgraph.cc @@ -149,6 +149,16 @@ gr_flowgraph::check_valid_port(gr_io_signature_sptr sig, int port) } } +void +gr_flowgraph::check_valid_port(const gr_msg_endpoint &e) +{ + if (GR_FLOWGRAPH_DEBUG) + std::cout << "check_valid_port( " << e.block() << ", " << e.port() << ")\n"; + + if(!e.block()->has_msg_port(e.port())) + throw std::invalid_argument("invalid msg port in connect() or disconnect()"); +} + void gr_flowgraph::check_dst_not_used(const gr_endpoint &dst) { @@ -181,8 +191,10 @@ gr_flowgraph::calc_used_blocks() gr_basic_block_vector_t tmp; // make sure free standing message blocks are included - for (gr_basic_block_vector_t::iterator it=d_msgblocks.begin(); it!=d_msgblocks.end(); it++){ - tmp.push_back(*it); + for (gr_msg_edge_viter_t p = d_msg_edges.begin(); p != d_msg_edges.end(); p++) { +// for now only blocks receiving messages get a thread context - uncomment to allow senders to also obtain one +// tmp.push_back(p->src().block()); + tmp.push_back(p->dst().block()); } // Collect all blocks in the edge list @@ -477,7 +489,27 @@ gr_flowgraph::topological_dfs_visit(gr_basic_block_sptr block, gr_basic_block_ve output.push_back(block); } -void gr_flowgraph::add_msg_block(gr_basic_block_sptr blk){ - d_msgblocks.push_back(blk); +void gr_flowgraph::connect(const gr_msg_endpoint &src, const gr_msg_endpoint &dst){ + check_valid_port(src); + check_valid_port(dst); + for (gr_msg_edge_viter_t p = d_msg_edges.begin(); p != d_msg_edges.end(); p++) { + if(p->src() == src && p->dst() == dst){ + throw std::runtime_error("connect called on already connected edge!"); + } + } + d_msg_edges.push_back(gr_msg_edge(src,dst)); } +void gr_flowgraph::disconnect(const gr_msg_endpoint &src, const gr_msg_endpoint &dst){ + check_valid_port(src); + check_valid_port(dst); + for (gr_msg_edge_viter_t p = d_msg_edges.begin(); p != d_msg_edges.end(); p++) { + if(p->src() == src && p->dst() == dst){ + d_msg_edges.erase(p); + return; + } + } + throw std::runtime_error("disconnect called on non-connected edge!"); +} + + -- cgit