gnuradio之flowgraph和top_block

一般的gnuradio开发方式是底层的信号处理模块采用C++编写,这样可以提高处理效率;而模块之间的连接使用Python,这是因为Python提供了更方便的操作接口,使用起来更方便。然而分析gnuradio的源代码可以发现,gnuradio中的流图和顶层模块top_block都是通过C++编写的:

流图类:

/*!
   * \brief Class representing a directed, acyclic graph of basic blocks
   * \ingroup internal
   */
  class GR_RUNTIME_API flowgraph
  {
  public:
    friend GR_RUNTIME_API flowgraph_sptr make_flowgraph();

    /*!
     * \brief Destruct an arbitrary flowgraph
     */
    virtual ~flowgraph();

    /*!
     * \brief Connect two endpoints
     * \details
     * Checks the validity of both endpoints, and whether the
     * destination is unused so far, then adds the edge to the internal list of
     * edges.
     */
    void connect(const endpoint &src, const endpoint &dst);

    /*!
     * \brief Disconnect two endpoints
     */
    void disconnect(const endpoint &src, const endpoint &dst);

    /*!
     * \brief convenience wrapper; used to connect two endpoints
     */
    void connect(basic_block_sptr src_block, int src_port,
                 basic_block_sptr dst_block, int dst_port);

    /*!
     * \brief convenience wrapper; used to disconnect two endpoints
     */
    void disconnect(basic_block_sptr src_block, int src_port,
                    basic_block_sptr dst_block, int dst_port);

    /*!
     * \brief Connect two message endpoints
     * \details
     * Checks the validity of both endpoints, then adds the edge to the
     * internal list of edges.
     */
    void connect(const msg_endpoint &src, const msg_endpoint &dst);

    /*!
     * \brief Disconnect two message endpoints
     */
    void disconnect(const msg_endpoint &src, const msg_endpoint &dst);

    /*!
     * \brief Validate flow graph
     * \details
     * Gathers all used blocks, checks the contiguity of all connected in- and
     * outputs, and calls the check_topology method of each block.
     */
    void validate();

    /*!
     * \brief Clear existing flowgraph
     */
    void clear();

    /*!
     * \brief Get vector of edges
     */
    const edge_vector_t &edges() const { return d_edges; }

    /*!
     * \brief Get vector of message edges
     */
    const msg_edge_vector_t &msg_edges() const { return d_msg_edges; }

    /*!
     * \brief calculates all used blocks in a flow graph
     * \details
     * Iterates over all message edges and stream edges, noting both endpoints in a vector.
     *
     * \return a unique vector of used blocks
     */
    basic_block_vector_t calc_used_blocks();

    /*!
     * \brief topologically sort blocks
     * \details
     * Uses depth-first search to return a sorted vector of blocks
     *
     * \return toplogically sorted vector of blocks.  All the sources come first.
     */
    basic_block_vector_t topological_sort(basic_block_vector_t &blocks);

    /*!
     * \brief Calculate vector of disjoint graph partions
     * \return vector of disjoint vectors of topologically sorted blocks
     */
    std::vector<basic_block_vector_t> partition();

  protected:
    basic_block_vector_t d_blocks;
    edge_vector_t d_edges;
    msg_edge_vector_t d_msg_edges;

    flowgraph();
    std::vector<int> calc_used_ports(basic_block_sptr block, bool check_inputs);
    basic_block_vector_t calc_downstream_blocks(basic_block_sptr block, int port);
    edge_vector_t calc_upstream_edges(basic_block_sptr block);
    bool has_block_p(basic_block_sptr block);
    edge calc_upstream_edge(basic_block_sptr block, int port);

  private:
    void check_valid_port(gr::io_signature::sptr sig, int port);
    void check_valid_port(const msg_endpoint &e);
    void check_dst_not_used(const endpoint &dst);
    void check_type_match(const endpoint &src, const endpoint &dst);
    edge_vector_t calc_connections(basic_block_sptr block, bool check_inputs); // false=use outputs
    void check_contiguity(basic_block_sptr block, const std::vector<int> &used_ports, bool check_inputs);

    basic_block_vector_t calc_downstream_blocks(basic_block_sptr block);
    basic_block_vector_t calc_reachable_blocks(basic_block_sptr block, basic_block_vector_t &blocks);
    void reachable_dfs_visit(basic_block_sptr block, basic_block_vector_t &blocks);
    basic_block_vector_t calc_adjacent_blocks(basic_block_sptr block, basic_block_vector_t &blocks);
    basic_block_vector_t sort_sources_first(basic_block_vector_t &blocks);
    bool source_p(basic_block_sptr block);
    void topological_dfs_visit(basic_block_sptr block, basic_block_vector_t &output);
  };
顶层模块top_block类:
/*!
   *\brief Top-level hierarchical block representing a flowgraph
   * \ingroup container_blk
   */
  class GR_RUNTIME_API top_block : public hier_block2
  {
  private:
    friend GR_RUNTIME_API top_block_sptr
      make_top_block(const std::string &name);

    top_block_impl *d_impl;

  protected:
    top_block(const std::string &name);

  public:
    ~top_block();

    /*!
     * \brief The simple interface to running a flowgraph.
     *
     * Calls start() then wait(). Used to run a flowgraph that will
     * stop on its own, or when another thread will call stop().
     *
     * \param max_noutput_items the maximum number of output items
     * allowed for any block in the flowgraph. This passes through to
     * the start function; see that function for more details.
     */
    void run(int max_noutput_items=100000000);

    /*!
     * Start the contained flowgraph. Creates one or more threads to
     * execute the flow graph. Returns to the caller once the threads
     * are created. Calling start() on a top_block that is already
     * started IS an error.
     *
     * \param max_noutput_items the maximum number of output items
     * allowed for any block in the flowgraph; the noutput_items can
     * always be less than this, but this will cap it as a
     * maximum. Use this to adjust the maximum latency a flowgraph can
     * exhibit.
     */
    void start(int max_noutput_items=100000000);

    /*!
     * Stop the running flowgraph. Notifies each thread created by the
     * scheduler to shutdown, then returns to caller. Calling stop()
     * on a top_block that is already stopped IS NOT an error.
     */
    void stop();

    /*!
     * Wait for a flowgraph to complete. Flowgraphs complete when
     * either (1) all blocks indicate that they are done (typically
     * only when using blocks.file_source, or blocks.head, or (2)
     * after stop() has been called to request shutdown. Calling wait
     * on a top_block that is not running IS NOT an error (wait
     * returns w/o blocking).
     */
    void wait();

    /*!
     * Lock a flowgraph in preparation for reconfiguration. When an
     * equal number of calls to lock() and unlock() have occurred, the
     * flowgraph will be reconfigured.
     *
     * N.B. lock() and unlock() may not be called from a flowgraph
     * thread (E.g., block::work method) or deadlock will occur
     * when reconfiguration happens.
     */
    virtual void lock();

    /*!
     * Unlock a flowgraph in preparation for reconfiguration. When an
     * equal number of calls to lock() and unlock() have occurred, the
     * flowgraph will be reconfigured.
     *
     * N.B. lock() and unlock() may not be called from a flowgraph thread
     * (E.g., block::work method) or deadlock will occur when
     * reconfiguration happens.
     */
    virtual void unlock();

    /*!
     * Returns a string that lists the edge connections in the
     * flattened flowgraph.
     */
    std::string edge_list();

    /*!
     * Returns a string that lists the msg edge connections in the
     * flattened flowgraph.
     */
    std::string msg_edge_list();

    /*!
     * Displays flattened flowgraph edges and block connectivity
     */
    void dump();

    //! Get the number of max noutput_items in the flowgraph
    int max_noutput_items();

    //! Set the maximum number of noutput_items in the flowgraph
    void set_max_noutput_items(int nmax);

    top_block_sptr to_top_block(); // Needed for Python type coercion

    void setup_rpc();
  };

可见C++的类中实现了比Python更多的功能,既然这些类都是通过C++编写的,虽然目前还没看到C++流图开发的例子,但理论上来说应该也可以通过C++开发流图。另一方面,由于Python并不能实现真正的多线程,使用C++开发可能也会得到更好地运行效果。


你可能感兴趣的:(gnuradio之flowgraph和top_block)