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