GNU Radio v3.6.2-149-ga6d285d9 C++ API
gr_basic_block.h
Go to the documentation of this file.
00001 /* -*- c++ -*- */
00002 /*
00003  * Copyright 2006,2008,2009,2011 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_BASIC_BLOCK_H
00024 #define INCLUDED_GR_BASIC_BLOCK_H
00025 
00026 #include <gr_core_api.h>
00027 #include <gr_runtime_types.h>
00028 #include <gr_sptr_magic.h>
00029 #include <boost/enable_shared_from_this.hpp>
00030 #include <boost/function.hpp>
00031 #include <gr_msg_accepter.h>
00032 #include <gr_io_signature.h>
00033 #include <string>
00034 #include <iostream>
00035 
00036 /*!
00037  * \brief The abstract base class for all signal processing blocks.
00038  * \ingroup internal
00039  *
00040  * Basic blocks are the bare abstraction of an entity that has a name,
00041  * a set of inputs and outputs, and a message queue.  These are never instantiated
00042  * directly; rather, this is the abstract parent class of both gr_hier_block,
00043  * which is a recursive container, and gr_block, which implements actual
00044  * signal processing functions.
00045  */
00046 
00047 class GR_CORE_API gr_basic_block : public gr_msg_accepter, public boost::enable_shared_from_this<gr_basic_block>
00048 {
00049     typedef boost::function<void(pmt::pmt_t)> msg_handler_t;
00050 
00051 private:
00052     /*
00053      * This function is called by the runtime system to dispatch messages.
00054      *
00055      * The thread-safety guarantees mentioned in set_msg_handler are implemented
00056      * by the callers of this method.
00057      */
00058     void dispatch_msg(pmt::pmt_t msg)
00059     {
00060       if (d_msg_handler)        // Is there a handler?
00061         d_msg_handler(msg);     // Yes, invoke it.
00062     };
00063 
00064     msg_handler_t        d_msg_handler;
00065 
00066     /*
00067      * Used to expand the vectors that hold the min/max buffer sizes.
00068      *
00069      * Specifically, when -1 is used, the vectors are just initialized
00070      * with 1 value; this is used by the flat_flowgraph to expand when
00071      * required to add a new value for new ports on these blocks.
00072      */
00073     void expand_minmax_buffer(int port) {
00074       if((size_t)port >= d_max_output_buffer.size())
00075         set_max_output_buffer(port, -1);
00076       if((size_t)port >= d_min_output_buffer.size())
00077         set_min_output_buffer(port, -1);
00078     }
00079     
00080 protected:
00081     friend class gr_flowgraph;
00082     friend class gr_flat_flowgraph; // TODO: will be redundant
00083     friend class gr_tpb_thread_body;
00084 
00085     enum vcolor { WHITE, GREY, BLACK };
00086 
00087     std::string          d_name;
00088     gr_io_signature_sptr d_input_signature;
00089     gr_io_signature_sptr d_output_signature;
00090     long                 d_unique_id;
00091     vcolor               d_color;
00092     std::vector<long>    d_max_output_buffer;
00093     std::vector<long>    d_min_output_buffer;
00094 
00095     gr_basic_block(void){} //allows pure virtual interface sub-classes
00096 
00097     //! Protected constructor prevents instantiation by non-derived classes
00098     gr_basic_block(const std::string &name,
00099                    gr_io_signature_sptr input_signature,
00100                    gr_io_signature_sptr output_signature);
00101 
00102     //! may only be called during constructor
00103     void set_input_signature(gr_io_signature_sptr iosig) {
00104         d_input_signature = iosig;
00105     }
00106 
00107     //! may only be called during constructor
00108     void set_output_signature(gr_io_signature_sptr iosig) {
00109         d_output_signature = iosig;
00110     }
00111 
00112     /*!
00113      * \brief Allow the flowgraph to set for sorting and partitioning
00114      */
00115     void set_color(vcolor color) { d_color = color; }
00116     vcolor color() const { return d_color; }
00117 
00118 public:
00119     virtual ~gr_basic_block();
00120     long unique_id() const { return d_unique_id; }
00121     std::string name() const { return d_name; }
00122     gr_io_signature_sptr input_signature() const  { return d_input_signature; }
00123     gr_io_signature_sptr output_signature() const { return d_output_signature; }
00124     gr_basic_block_sptr to_basic_block(); // Needed for Python type coercion
00125 
00126     /*!
00127      * \brief Returns max buffer size on output port \p i.
00128      */
00129     long max_output_buffer(size_t i) {
00130       if(i >= d_max_output_buffer.size())
00131         throw std::invalid_argument("gr_basic_block::max_output_buffer: port out of range.");
00132       return d_max_output_buffer[i];
00133     }
00134 
00135     /*!
00136      * \brief Sets max buffer size on all output ports.
00137      */
00138     void set_max_output_buffer(long max_output_buffer) { 
00139       for(int i=0; i<output_signature()->max_streams(); i++) {
00140         set_max_output_buffer(i, max_output_buffer);
00141       }
00142     }
00143 
00144     /*!
00145      * \brief Sets max buffer size on output port \p port.
00146      */
00147     void set_max_output_buffer(int port, long max_output_buffer) {
00148       if((size_t)port >= d_max_output_buffer.size())
00149         d_max_output_buffer.push_back(max_output_buffer);
00150       else
00151         d_max_output_buffer[port] = max_output_buffer; 
00152     }
00153 
00154     /*!
00155      * \brief Returns min buffer size on output port \p i.
00156      */
00157     long min_output_buffer(size_t i) {
00158       if(i >= d_min_output_buffer.size())
00159         throw std::invalid_argument("gr_basic_block::min_output_buffer: port out of range.");
00160       return d_min_output_buffer[i];
00161     }
00162 
00163     /*!
00164      * \brief Sets min buffer size on all output ports.
00165      */
00166     void set_min_output_buffer(long min_output_buffer) {
00167       for(int i=0; i<output_signature()->max_streams(); i++) {
00168         set_min_output_buffer(i, min_output_buffer);
00169       }
00170     }
00171 
00172     /*!
00173      * \brief Sets min buffer size on output port \p port.
00174      */
00175     void set_min_output_buffer(int port, long min_output_buffer) {
00176       if((size_t)port >= d_min_output_buffer.size())
00177         d_min_output_buffer.push_back(min_output_buffer);
00178       else
00179         d_min_output_buffer[port] = min_output_buffer; 
00180     }
00181 
00182     /*!
00183      * \brief Confirm that ninputs and noutputs is an acceptable combination.
00184      *
00185      * \param ninputs   number of input streams connected
00186      * \param noutputs  number of output streams connected
00187      *
00188      * \returns true if this is a valid configuration for this block.
00189      *
00190      * This function is called by the runtime system whenever the
00191      * topology changes.  Most classes do not need to override this.
00192      * This check is in addition to the constraints specified by the input
00193      * and output gr_io_signatures.
00194      */
00195     virtual bool check_topology(int ninputs, int noutputs) { return true; }
00196 
00197     /*!
00198      * \brief Set the callback that is fired when messages are available.
00199      *
00200      * \p msg_handler can be any kind of function pointer or function object
00201      * that has the signature:
00202      * <pre>
00203      *    void msg_handler(pmt::pmt msg);
00204      * </pre>
00205      *
00206      * (You may want to use boost::bind to massage your callable into the
00207      * correct form.  See gr_nop.{h,cc} for an example that sets up a class
00208      * method as the callback.)
00209      *
00210      * Blocks that desire to handle messages must call this method in their
00211      * constructors to register the handler that will be invoked when messages
00212      * are available.
00213      *
00214      * If the block inherits from gr_block, the runtime system will ensure that
00215      * msg_handler is called in a thread-safe manner, such that work and
00216      * msg_handler will never be called concurrently.  This allows msg_handler
00217      * to update state variables without having to worry about thread-safety
00218      * issues with work, general_work or another invocation of msg_handler.
00219      *
00220      * If the block inherits from gr_hier_block2, the runtime system will
00221      * ensure that no reentrant calls are made to msg_handler.
00222      */
00223     template <typename T> void set_msg_handler(T msg_handler){
00224       d_msg_handler = msg_handler_t(msg_handler);
00225     }
00226 };
00227 
00228 inline bool operator<(gr_basic_block_sptr lhs, gr_basic_block_sptr rhs)
00229 {
00230   return lhs->unique_id() < rhs->unique_id();
00231 }
00232 
00233 typedef std::vector<gr_basic_block_sptr> gr_basic_block_vector_t;
00234 typedef std::vector<gr_basic_block_sptr>::iterator gr_basic_block_viter_t;
00235 
00236 GR_CORE_API long gr_basic_block_ncurrently_allocated();
00237 
00238 inline std::ostream &operator << (std::ostream &os, gr_basic_block_sptr basic_block)
00239 {
00240     os << basic_block->name() << "(" << basic_block->unique_id() << ")";
00241     return os;
00242 }
00243 
00244 #endif /* INCLUDED_GR_BASIC_BLOCK_H */