GNU Radio 3.7.1 C++ API
flowgraph.h
Go to the documentation of this file.
00001 /* -*- c++ -*- */
00002 /*
00003  * Copyright 2006,2007,2013 Free Software Foundation, Inc.
00004  *
00005  * This file is part of GNU Radio
00006  *
00007  * GNU Radio is free software; you can redistribute it and/or modify
00008  * it under the terms of the GNU General Public License as published by
00009  * the Free Software Foundation; either version 3, or (at your option)
00010  * any later version.
00011  *
00012  * GNU Radio is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU General Public License
00018  * along with GNU Radio; see the file COPYING.  If not, write to
00019  * the Free Software Foundation, Inc., 51 Franklin Street,
00020  * Boston, MA 02110-1301, USA.
00021  */
00022 
00023 #ifndef INCLUDED_GR_RUNTIME_FLOWGRAPH_H
00024 #define INCLUDED_GR_RUNTIME_FLOWGRAPH_H
00025 
00026 #include <gnuradio/api.h>
00027 #include <gnuradio/basic_block.h>
00028 #include <gnuradio/io_signature.h>
00029 #include <iostream>
00030 
00031 namespace gr {
00032 
00033   /*!
00034    * \brief Class representing a specific input or output graph endpoint
00035    * \ingroup internal
00036    */
00037   class GR_RUNTIME_API endpoint
00038   {
00039   private:
00040     basic_block_sptr d_basic_block;
00041     int d_port;
00042 
00043   public:
00044     endpoint() : d_basic_block(), d_port(0) { }
00045     endpoint(basic_block_sptr block, int port) { d_basic_block = block; d_port = port; }
00046     basic_block_sptr block() const { return d_basic_block; }
00047     int port() const { return d_port; }
00048 
00049     bool operator==(const endpoint &other) const;
00050   };
00051 
00052   inline bool endpoint::operator==(const endpoint &other) const
00053   {
00054     return (d_basic_block == other.d_basic_block &&
00055             d_port == other.d_port);
00056   }
00057 
00058   class GR_RUNTIME_API msg_endpoint
00059   {
00060   private:
00061     basic_block_sptr d_basic_block;
00062     pmt::pmt_t d_port;
00063     bool d_is_hier;
00064 
00065   public:
00066     msg_endpoint() : d_basic_block(), d_port(pmt::PMT_NIL) { }
00067     msg_endpoint(basic_block_sptr block, pmt::pmt_t port, bool is_hier=false) {
00068       d_basic_block = block; d_port = port; d_is_hier = is_hier;
00069     }
00070     basic_block_sptr block() const { return d_basic_block; }
00071     pmt::pmt_t port() const { return d_port; }
00072     bool is_hier() const { return d_is_hier; }
00073     void set_hier(bool h) { d_is_hier = h; }
00074 
00075     bool operator==(const msg_endpoint &other) const;
00076   };
00077 
00078   inline bool
00079   msg_endpoint::operator==(const msg_endpoint &other) const
00080   {
00081     return (d_basic_block == other.d_basic_block &&
00082             pmt::equal(d_port, other.d_port));
00083   }
00084 
00085   // Hold vectors of gr::endpoint objects
00086   typedef std::vector<endpoint> endpoint_vector_t;
00087   typedef std::vector<endpoint>::iterator endpoint_viter_t;
00088 
00089   /*!
00090    *\brief Class representing a connection between to graph endpoints
00091    */
00092   class GR_RUNTIME_API edge
00093   {
00094   public:
00095     edge() : d_src(), d_dst() { };
00096     edge(const endpoint &src, const endpoint &dst)
00097       : d_src(src), d_dst(dst) { }
00098     ~edge();
00099 
00100     const endpoint &src() const { return d_src; }
00101     const endpoint &dst() const { return d_dst; }
00102 
00103   private:
00104     endpoint d_src;
00105     endpoint d_dst;
00106   };
00107 
00108   // Hold vectors of gr::edge objects
00109   typedef std::vector<edge> edge_vector_t;
00110   typedef std::vector<edge>::iterator edge_viter_t;
00111 
00112 
00113   /*!
00114    *\brief Class representing a msg connection between to graph msg endpoints
00115    */
00116   class GR_RUNTIME_API msg_edge
00117   {
00118   public:
00119     msg_edge() : d_src(), d_dst() { };
00120     msg_edge(const msg_endpoint &src, const msg_endpoint &dst)
00121       : d_src(src), d_dst(dst) { }
00122     ~msg_edge() {}
00123 
00124     const msg_endpoint &src() const { return d_src; }
00125     const msg_endpoint &dst() const { return d_dst; }
00126 
00127   private:
00128     msg_endpoint d_src;
00129     msg_endpoint d_dst;
00130   };
00131 
00132   // Hold vectors of gr::msg_edge objects
00133   typedef std::vector<msg_edge> msg_edge_vector_t;
00134   typedef std::vector<msg_edge>::iterator msg_edge_viter_t;
00135 
00136   // Create a shared pointer to a heap allocated flowgraph
00137   // (types defined in runtime_types.h)
00138   GR_RUNTIME_API flowgraph_sptr make_flowgraph();
00139 
00140   /*!
00141    * \brief Class representing a directed, acyclic graph of basic blocks
00142    * \ingroup internal
00143    */
00144   class GR_RUNTIME_API flowgraph
00145   {
00146   public:
00147     friend GR_RUNTIME_API flowgraph_sptr make_flowgraph();
00148 
00149     // Destruct an arbitrary flowgraph
00150     ~flowgraph();
00151 
00152     // Connect two endpoints
00153     void connect(const endpoint &src, const endpoint &dst);
00154 
00155     // Disconnect two endpoints
00156     void disconnect(const endpoint &src, const endpoint &dst);
00157 
00158     // Connect an output port to an input port (convenience)
00159     void connect(basic_block_sptr src_block, int src_port,
00160                  basic_block_sptr dst_block, int dst_port);
00161 
00162     // Disconnect an input port from an output port (convenience)
00163     void disconnect(basic_block_sptr src_block, int src_port,
00164                     basic_block_sptr dst_block, int dst_port);
00165 
00166     // Connect two msg endpoints
00167     void connect(const msg_endpoint &src, const msg_endpoint &dst);
00168   
00169     // Disconnect two msg endpoints
00170     void disconnect(const msg_endpoint &src, const msg_endpoint &dst);
00171 
00172     // Validate connectivity, raise exception if invalid
00173     void validate();
00174 
00175     // Clear existing flowgraph
00176     void clear();
00177 
00178     // Return vector of edges
00179     const edge_vector_t &edges() const { return d_edges; }
00180   
00181     // Return vector of msg edges
00182     const msg_edge_vector_t &msg_edges() const { return d_msg_edges; }
00183 
00184     // Return vector of connected blocks
00185     basic_block_vector_t calc_used_blocks();
00186 
00187     // Return toplogically sorted vector of blocks.  All the sources come first.
00188     basic_block_vector_t topological_sort(basic_block_vector_t &blocks);
00189 
00190     // Return vector of vectors of disjointly connected blocks,
00191     // topologically sorted.
00192     std::vector<basic_block_vector_t> partition();
00193 
00194   protected:
00195     basic_block_vector_t d_blocks;
00196     edge_vector_t d_edges;
00197     msg_edge_vector_t d_msg_edges;
00198 
00199     flowgraph();
00200     std::vector<int> calc_used_ports(basic_block_sptr block, bool check_inputs);
00201     basic_block_vector_t calc_downstream_blocks(basic_block_sptr block, int port);
00202     edge_vector_t calc_upstream_edges(basic_block_sptr block);
00203     bool has_block_p(basic_block_sptr block);
00204     edge calc_upstream_edge(basic_block_sptr block, int port);
00205 
00206   private:
00207     void check_valid_port(gr::io_signature::sptr sig, int port);
00208     void check_valid_port(const msg_endpoint &e);
00209     void check_dst_not_used(const endpoint &dst);
00210     void check_type_match(const endpoint &src, const endpoint &dst);
00211     edge_vector_t calc_connections(basic_block_sptr block, bool check_inputs); // false=use outputs
00212     void check_contiguity(basic_block_sptr block, const std::vector<int> &used_ports, bool check_inputs);
00213 
00214     basic_block_vector_t calc_downstream_blocks(basic_block_sptr block);
00215     basic_block_vector_t calc_reachable_blocks(basic_block_sptr block, basic_block_vector_t &blocks);
00216     void reachable_dfs_visit(basic_block_sptr block, basic_block_vector_t &blocks);
00217     basic_block_vector_t calc_adjacent_blocks(basic_block_sptr block, basic_block_vector_t &blocks);
00218     basic_block_vector_t sort_sources_first(basic_block_vector_t &blocks);
00219     bool source_p(basic_block_sptr block);
00220     void topological_dfs_visit(basic_block_sptr block, basic_block_vector_t &output);
00221   };
00222 
00223   // Convenience functions
00224   inline
00225   void flowgraph::connect(basic_block_sptr src_block, int src_port,
00226                           basic_block_sptr dst_block, int dst_port)
00227   {
00228     connect(endpoint(src_block, src_port),
00229             endpoint(dst_block, dst_port));
00230   }
00231 
00232   inline
00233   void flowgraph::disconnect(basic_block_sptr src_block, int src_port,
00234                              basic_block_sptr dst_block, int dst_port)
00235   {
00236     disconnect(endpoint(src_block, src_port),
00237                endpoint(dst_block, dst_port));
00238   }
00239 
00240   inline std::ostream&
00241   operator <<(std::ostream &os, const endpoint endp)
00242   {
00243     os << endp.block()->alias() << ":" << endp.port();
00244     return os;
00245   }
00246 
00247   inline std::ostream&
00248   operator <<(std::ostream &os, const edge edge)
00249   {
00250     os << edge.src() << "->" << edge.dst();
00251     return os;
00252   }
00253 
00254   inline std::ostream&
00255   operator <<(std::ostream &os, const msg_endpoint endp)
00256   {
00257     os << endp.block()->alias() << ":" << pmt::symbol_to_string(endp.port());
00258     return os;
00259   }
00260 
00261   inline std::ostream&
00262   operator <<(std::ostream &os, const msg_edge edge)
00263   {
00264     os << edge.src() << "->" << edge.dst();
00265     return os;
00266   }
00267 
00268 } /* namespace gr */
00269 
00270 #endif /* INCLUDED_GR_RUNTIME_FLOWGRAPH_H */