GNU Radio Manual and C++ API Reference  3.7.13.4
The Free & Open Software Radio Ecosystem
basic_block.h
Go to the documentation of this file.
1 /* -*- c++ -*- */
2 /*
3  * Copyright 2006,2008,2009,2011,2013 Free Software Foundation, Inc.
4  *
5  * This file is part of GNU Radio
6  *
7  * GNU Radio is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 3, or (at your option)
10  * any later version.
11  *
12  * GNU Radio is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with GNU Radio; see the file COPYING. If not, write to
19  * the Free Software Foundation, Inc., 51 Franklin Street,
20  * Boston, MA 02110-1301, USA.
21  */
22 
23 #ifndef INCLUDED_GR_BASIC_BLOCK_H
24 #define INCLUDED_GR_BASIC_BLOCK_H
25 
26 #include <gnuradio/api.h>
27 #include <gnuradio/sptr_magic.h>
28 #include <gnuradio/msg_accepter.h>
29 #include <gnuradio/runtime_types.h>
30 #include <gnuradio/io_signature.h>
31 #include <gnuradio/thread/thread.h>
32 #include <boost/enable_shared_from_this.hpp>
33 #include <boost/function.hpp>
34 #include <boost/foreach.hpp>
35 #include <boost/thread/condition_variable.hpp>
36 #include <iostream>
37 #include <string>
38 #include <deque>
39 #include <map>
40 
41 #ifdef GR_CTRLPORT
43 #endif
44 
45 namespace gr {
46 
47  /*!
48  * \brief The abstract base class for all signal processing blocks.
49  * \ingroup internal
50  *
51  * Basic blocks are the bare abstraction of an entity that has a
52  * name, a set of inputs and outputs, and a message queue. These
53  * are never instantiated directly; rather, this is the abstract
54  * parent class of both gr_hier_block, which is a recursive
55  * container, and block, which implements actual signal
56  * processing functions.
57  */
59  public boost::enable_shared_from_this<basic_block>
60  {
61  typedef boost::function<void(pmt::pmt_t)> msg_handler_t;
62 
63  private:
64  typedef std::map<pmt::pmt_t , msg_handler_t, pmt::comparator> d_msg_handlers_t;
65  d_msg_handlers_t d_msg_handlers;
66 
67  typedef std::deque<pmt::pmt_t> msg_queue_t;
68  typedef std::map<pmt::pmt_t, msg_queue_t, pmt::comparator> msg_queue_map_t;
69  typedef std::map<pmt::pmt_t, msg_queue_t, pmt::comparator>::iterator msg_queue_map_itr;
70  std::map<pmt::pmt_t, boost::shared_ptr<boost::condition_variable>, pmt::comparator> msg_queue_ready;
71 
72  gr::thread::mutex mutex; //< protects all vars
73 
74  protected:
75  friend class flowgraph;
76  friend class flat_flowgraph; // TODO: will be redundant
77  friend class tpb_thread_body;
78 
79  enum vcolor { WHITE, GREY, BLACK };
80 
81  std::string d_name;
86  std::string d_symbol_name;
87  std::string d_symbol_alias;
89  bool d_rpc_set;
90 
91  msg_queue_map_t msg_queue;
92  std::vector<boost::any> d_rpc_vars; // container for all RPC variables
93 
94  basic_block(void) {} // allows pure virtual interface sub-classes
95 
96  //! Protected constructor prevents instantiation by non-derived classes
97  basic_block(const std::string &name,
98  gr::io_signature::sptr input_signature,
99  gr::io_signature::sptr output_signature);
100 
101  //! may only be called during constructor
103  d_input_signature = iosig;
104  }
105 
106  //! may only be called during constructor
108  d_output_signature = iosig;
109  }
110 
111  /*!
112  * \brief Allow the flowgraph to set for sorting and partitioning
113  */
114  void set_color(vcolor color) { d_color = color; }
115  vcolor color() const { return d_color; }
116 
117  /*!
118  * \brief Tests if there is a handler attached to port \p which_port
119  */
120  virtual bool has_msg_handler(pmt::pmt_t which_port) {
121  return (d_msg_handlers.find(which_port) != d_msg_handlers.end());
122  }
123 
124  /*
125  * This function is called by the runtime system to dispatch messages.
126  *
127  * The thread-safety guarantees mentioned in set_msg_handler are
128  * implemented by the callers of this method.
129  */
130  virtual void dispatch_msg(pmt::pmt_t which_port, pmt::pmt_t msg)
131  {
132  // AA Update this
133  if(has_msg_handler(which_port)) { // Is there a handler?
134  d_msg_handlers[which_port](msg); // Yes, invoke it.
135  }
136  }
137 
138  // Message passing interface
140 
141  public:
142  pmt::pmt_t message_subscribers(pmt::pmt_t port);
143  virtual ~basic_block();
144  long unique_id() const { return d_unique_id; }
145  long symbolic_id() const { return d_symbolic_id; }
146 
147  /*! The name of the block */
148  std::string name() const { return d_name; }
149 
150  /*!
151  * The sybolic name of the block, which is used in the
152  * block_registry. The name is assigned by the block's constructor
153  * and never changes during the life of the block.
154  */
155  std::string symbol_name() const { return d_symbol_name; }
156 
157  gr::io_signature::sptr input_signature() const { return d_input_signature; }
158  gr::io_signature::sptr output_signature() const { return d_output_signature; }
159  basic_block_sptr to_basic_block(); // Needed for Python type coercion
160 
161  /*!
162  * True if the block has an alias (see set_block_alias).
163  */
164  bool alias_set() { return !d_symbol_alias.empty(); }
165 
166  /*!
167  * Returns the block's alias as a string.
168  */
169  std::string alias(){ return alias_set()?d_symbol_alias:symbol_name(); }
170 
171  /*!
172  * Returns the block's alias as PMT.
173  */
174  pmt::pmt_t alias_pmt(){ return pmt::intern(alias()); }
175 
176  /*!
177  * Set's a new alias for the block; also adds an entry into the
178  * block_registry to get the block using either the alias or the
179  * original symbol name.
180  */
181  void set_block_alias(std::string name);
182 
183  // ** Message passing interface **
184  void message_port_register_in(pmt::pmt_t port_id);
185  void message_port_register_out(pmt::pmt_t port_id);
186  void message_port_pub(pmt::pmt_t port_id, pmt::pmt_t msg);
187  void message_port_sub(pmt::pmt_t port_id, pmt::pmt_t target);
188  void message_port_unsub(pmt::pmt_t port_id, pmt::pmt_t target);
189 
190  virtual bool message_port_is_hier(pmt::pmt_t port_id) { (void) port_id; return false; }
191  virtual bool message_port_is_hier_in(pmt::pmt_t port_id) { (void) port_id; return false; }
192  virtual bool message_port_is_hier_out(pmt::pmt_t port_id) { (void) port_id; return false; }
193 
194  /*!
195  * \brief Get input message port names.
196  *
197  * Returns the available input message ports for a block. The
198  * return object is a PMT vector that is filled with PMT symbols.
199  */
200  pmt::pmt_t message_ports_in();
201 
202  /*!
203  * \brief Get output message port names.
204  *
205  * Returns the available output message ports for a block. The
206  * return object is a PMT vector that is filled with PMT symbols.
207  */
208  pmt::pmt_t message_ports_out();
209 
210  /*!
211  * Accept msg, place in queue, arrange for thread to be awakened if it's not already.
212  */
213  void _post(pmt::pmt_t which_port, pmt::pmt_t msg);
214 
215  //! is the queue empty?
216  bool empty_p(pmt::pmt_t which_port) {
217  if(msg_queue.find(which_port) == msg_queue.end())
218  throw std::runtime_error("port does not exist!");
219  return msg_queue[which_port].empty();
220  }
221  bool empty_p() {
222  bool rv = true;
223  BOOST_FOREACH(msg_queue_map_t::value_type &i, msg_queue) {
224  rv &= msg_queue[i.first].empty();
225  }
226  return rv;
227  }
228 
229  //! are all msg ports with handlers empty?
230  bool empty_handled_p(pmt::pmt_t which_port){
231  return (empty_p(which_port) || !has_msg_handler(which_port));
232  }
234  bool rv = true;
235  BOOST_FOREACH(msg_queue_map_t::value_type &i, msg_queue) {
236  rv &= empty_handled_p(i.first);
237  }
238  return rv;
239  }
240 
241  //! How many messages in the queue?
242  size_t nmsgs(pmt::pmt_t which_port) {
243  if(msg_queue.find(which_port) == msg_queue.end())
244  throw std::runtime_error("port does not exist!");
245  return msg_queue[which_port].size();
246  }
247 
248  //| Acquires and release the mutex
249  void insert_tail( pmt::pmt_t which_port, pmt::pmt_t msg);
250  /*!
251  * \returns returns pmt at head of queue or pmt::pmt_t() if empty.
252  */
253  pmt::pmt_t delete_head_nowait( pmt::pmt_t which_port);
254 
255  /*!
256  * \param[in] which_port The message port from which to get the message.
257  * \param[in] millisec Optional timeout value (0=no timeout).
258  * \returns returns pmt at head of queue or pmt::pmt_t() if empty.
259  */
260  pmt::pmt_t delete_head_blocking(pmt::pmt_t which_port, unsigned int millisec = 0);
261 
262  msg_queue_t::iterator get_iterator(pmt::pmt_t which_port) {
263  return msg_queue[which_port].begin();
264  }
265 
266  void erase_msg(pmt::pmt_t which_port, msg_queue_t::iterator it) {
267  msg_queue[which_port].erase(it);
268  }
269 
270  virtual bool has_msg_port(pmt::pmt_t which_port) {
271  if(msg_queue.find(which_port) != msg_queue.end()) {
272  return true;
273  }
274  if(pmt::dict_has_key(d_message_subscribers, which_port)) {
275  return true;
276  }
277  return false;
278  }
279 
280  const msg_queue_map_t& get_msg_map(void) const {
281  return msg_queue;
282  }
283 
284 #ifdef GR_CTRLPORT
285  /*!
286  * \brief Add an RPC variable (get or set).
287  *
288  * Using controlport, we create new getters/setters and need to
289  * store them. Each block has a vector to do this, and these never
290  * need to be accessed again once they are registered with the RPC
291  * backend. This function takes a
292  * boost::shared_sptr<rpcbasic_base> so that when the block is
293  * deleted, all RPC registered variables are cleaned up.
294  *
295  * \param s an rpcbasic_sptr of the new RPC variable register to store.
296  */
297  void add_rpc_variable(rpcbasic_sptr s)
298  {
299  d_rpc_vars.push_back(s);
300  }
301 #endif /* GR_CTRLPORT */
302 
303  /*!
304  * \brief Set up the RPC registered variables.
305  *
306  * This must be overloaded by a block that wants to use
307  * controlport. This is where rpcbasic_register_{get,set} pointers
308  * are created, which then get wrapped as shared pointers
309  * (rpcbasic_sptr(...)) and stored using add_rpc_variable.
310  */
311  virtual void setup_rpc() {};
312 
313  /*!
314  * \brief Ask if this block has been registered to the RPC.
315  *
316  * We can only register a block once, so we use this to protect us
317  * from calling it multiple times.
318  */
319  bool is_rpc_set() { return d_rpc_set; }
320 
321  /*!
322  * \brief When the block is registered with the RPC, set this.
323  */
324  void rpc_set() { d_rpc_set = true; }
325 
326  /*!
327  * \brief Confirm that ninputs and noutputs is an acceptable combination.
328  *
329  * \param ninputs number of input streams connected
330  * \param noutputs number of output streams connected
331  *
332  * \returns true if this is a valid configuration for this block.
333  *
334  * This function is called by the runtime system whenever the
335  * topology changes. Most classes do not need to override this.
336  * This check is in addition to the constraints specified by the
337  * input and output gr::io_signatures.
338  */
339  virtual bool check_topology(int ninputs, int noutputs) {
340  (void)ninputs;
341  (void)noutputs;
342  return true;
343  }
344 
345  /*!
346  * \brief Set the callback that is fired when messages are available.
347  *
348  * \p msg_handler can be any kind of function pointer or function object
349  * that has the signature:
350  * <pre>
351  * void msg_handler(pmt::pmt msg);
352  * </pre>
353  *
354  * (You may want to use boost::bind to massage your callable into
355  * the correct form. See gr::blocks::nop for an example that sets
356  * up a class method as the callback.)
357  *
358  * Blocks that desire to handle messages must call this method in
359  * their constructors to register the handler that will be invoked
360  * when messages are available.
361  *
362  * If the block inherits from block, the runtime system will
363  * ensure that msg_handler is called in a thread-safe manner, such
364  * that work and msg_handler will never be called concurrently.
365  * This allows msg_handler to update state variables without
366  * having to worry about thread-safety issues with work,
367  * general_work or another invocation of msg_handler.
368  *
369  * If the block inherits from hier_block2, the runtime system
370  * will ensure that no reentrant calls are made to msg_handler.
371  */
372  template <typename T> void set_msg_handler(pmt::pmt_t which_port, T msg_handler) {
373  if(msg_queue.find(which_port) == msg_queue.end()) {
374  throw std::runtime_error("attempt to set_msg_handler() on bad input message port!");
375  }
376  d_msg_handlers[which_port] = msg_handler_t(msg_handler);
377  }
378 
379  virtual void set_processor_affinity(const std::vector<int> &mask)
380  { throw std::runtime_error("set_processor_affinity not overloaded in child class."); }
381 
383  { throw std::runtime_error("unset_processor_affinity not overloaded in child class."); }
384 
385  virtual std::vector<int> processor_affinity()
386  { throw std::runtime_error("processor_affinity not overloaded in child class."); }
387  };
388 
389  inline bool operator<(basic_block_sptr lhs, basic_block_sptr rhs)
390  {
391  return lhs->unique_id() < rhs->unique_id();
392  }
393 
394  typedef std::vector<basic_block_sptr> basic_block_vector_t;
395  typedef std::vector<basic_block_sptr>::iterator basic_block_viter_t;
396 
398 
399  inline std::ostream &operator << (std::ostream &os, basic_block_sptr basic_block)
400  {
401  os << basic_block->name() << "(" << basic_block->unique_id() << ")";
402  return os;
403  }
404 
405 } /* namespace gr */
406 
407 #endif /* INCLUDED_GR_BASIC_BLOCK_H */
boost::shared_ptr< io_signature > sptr
Definition: io_signature.h:45
Provide a comparator function object to allow pmt use in stl types.
Definition: pmt.h:904
std::string d_symbol_alias
Definition: basic_block.h:87
void set_input_signature(gr::io_signature::sptr iosig)
may only be called during constructor
Definition: basic_block.h:102
size_t nmsgs(pmt::pmt_t which_port)
How many messages in the queue?
Definition: basic_block.h:242
virtual void setup_rpc()
Set up the RPC registered variables.
Definition: basic_block.h:311
std::string alias()
Definition: basic_block.h:169
virtual void set_processor_affinity(const std::vector< int > &mask)
Definition: basic_block.h:379
bool empty_p()
Definition: basic_block.h:221
std::string d_symbol_name
Definition: basic_block.h:86
bool is_rpc_set()
Ask if this block has been registered to the RPC.
Definition: basic_block.h:319
void set_color(vcolor color)
Allow the flowgraph to set for sorting and partitioning.
Definition: basic_block.h:114
virtual bool message_port_is_hier(pmt::pmt_t port_id)
Definition: basic_block.h:190
msg_queue_map_t msg_queue
Definition: basic_block.h:91
void erase_msg(pmt::pmt_t which_port, msg_queue_t::iterator it)
Definition: basic_block.h:266
virtual bool has_msg_handler(pmt::pmt_t which_port)
Tests if there is a handler attached to port which_port.
Definition: basic_block.h:120
bool empty_handled_p(pmt::pmt_t which_port)
are all msg ports with handlers empty?
Definition: basic_block.h:230
virtual std::vector< int > processor_affinity()
Definition: basic_block.h:385
Class representing a directed, acyclic graph of basic blocks.
Definition: flowgraph.h:144
PMT_API pmt_t intern(const std::string &s)
Alias for pmt_string_to_symbol.
void rpc_set()
When the block is registered with the RPC, set this.
Definition: basic_block.h:324
std::string name() const
Definition: basic_block.h:148
virtual bool has_msg_port(pmt::pmt_t which_port)
Definition: basic_block.h:270
Accepts messages and inserts them into a message queue, then notifies subclass gr::basic_block there ...
Definition: msg_accepter.h:35
#define GR_RUNTIME_API
Definition: gnuradio-runtime/include/gnuradio/api.h:30
long unique_id() const
Definition: basic_block.h:144
gr::io_signature::sptr d_input_signature
Definition: basic_block.h:82
gr::io_signature::sptr output_signature() const
Definition: basic_block.h:158
Include this header to use the message passing features.
Definition: logger.h:695
vcolor
Definition: basic_block.h:79
const msg_queue_map_t & get_msg_map(void) const
Definition: basic_block.h:280
The abstract base class for all signal processing blocks.Basic blocks are the bare abstraction of an ...
Definition: basic_block.h:58
gr::io_signature::sptr input_signature() const
Definition: basic_block.h:157
std::string d_name
Definition: basic_block.h:81
vcolor color() const
Definition: basic_block.h:115
basic_block(void)
Definition: basic_block.h:94
virtual bool message_port_is_hier_in(pmt::pmt_t port_id)
Definition: basic_block.h:191
virtual bool message_port_is_hier_out(pmt::pmt_t port_id)
Definition: basic_block.h:192
bool empty_p(pmt::pmt_t which_port)
is the queue empty?
Definition: basic_block.h:216
bool empty_handled_p()
Definition: basic_block.h:233
virtual bool check_topology(int ninputs, int noutputs)
Confirm that ninputs and noutputs is an acceptable combination.
Definition: basic_block.h:339
virtual void unset_processor_affinity()
Definition: basic_block.h:382
std::vector< boost::any > d_rpc_vars
Definition: basic_block.h:92
std::vector< basic_block_sptr > basic_block_vector_t
Definition: basic_block.h:394
msg_queue_t::iterator get_iterator(pmt::pmt_t which_port)
Definition: basic_block.h:262
long d_symbolic_id
Definition: basic_block.h:85
pmt::pmt_t alias_pmt()
Definition: basic_block.h:174
std::vector< basic_block_sptr >::iterator basic_block_viter_t
Definition: basic_block.h:395
gr::io_signature::sptr d_output_signature
Definition: basic_block.h:83
std::ostream & operator<<(std::ostream &os, basic_block_sptr basic_block)
Definition: basic_block.h:399
GR_RUNTIME_API long basic_block_ncurrently_allocated()
boost::mutex mutex
Definition: thread.h:48
PMT_API bool dict_has_key(const pmt_t &dict, const pmt_t &key)
Return true if key exists in dict.
long symbolic_id() const
Definition: basic_block.h:145
bool d_rpc_set
Definition: basic_block.h:89
boost::intrusive_ptr< pmt_base > pmt_t
typedef for shared pointer (transparent reference counting). See http://www.boost.org/libs/smart_ptr/smart_ptr.htm
Definition: pmt.h:56
virtual void dispatch_msg(pmt::pmt_t which_port, pmt::pmt_t msg)
Definition: basic_block.h:130
vcolor d_color
Definition: basic_block.h:88
Definition: basic_block.h:79
pmt::pmt_t d_message_subscribers
Definition: basic_block.h:139
void set_msg_handler(pmt::pmt_t which_port, T msg_handler)
Set the callback that is fired when messages are available.
Definition: basic_block.h:372
bool alias_set()
Definition: basic_block.h:164
long d_unique_id
Definition: basic_block.h:84
bool operator<(basic_block_sptr lhs, basic_block_sptr rhs)
Definition: basic_block.h:389
void set_output_signature(gr::io_signature::sptr iosig)
may only be called during constructor
Definition: basic_block.h:107
std::string symbol_name() const
Definition: basic_block.h:155
abstract class of message handlers
Definition: msg_handler.h:38