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