gnuradio之flowgraph和top_block

来源:互联网 发布:公务员网络培训学院 编辑:程序博客网 时间:2024/06/01 07:19

一般的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++开发可能也会得到更好地运行效果。


2 0
原创粉丝点击