GNU Radio v3.6.2-149-ga6d285d9 C++ API
|
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 */