GNU Radio Manual and C++ API Reference 3.10.2.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
130 /*!
131 * \brief This is meant to be called by derived classes (e.g. block) to get
132 * a shared pointer internally. This is needed because
133 * std::enable_shared_from_this doesn't seem to work with derived classes
134 * in an inheritance hierarchy.
135 */
136 template <typename Derived>
137 std::shared_ptr<Derived> shared_from_base()
138 {
139 return std::static_pointer_cast<Derived>(shared_from_this());
140 }
141
142public:
144 ~basic_block() override;
145 long unique_id() const { return d_unique_id; }
146 long symbolic_id() const { return d_symbolic_id; }
147
148 /*! The name of the block */
149 std::string name() const { return d_name; }
150
151 /*!
152 * The sybolic name of the block, which is used in the
153 * block_registry. The name is assigned by the block's constructor
154 * and never changes during the life of the block.
155 */
156 std::string symbol_name() const { return d_symbol_name; }
157 std::string identifier() const
158 {
159 return this->name() + "(" + std::to_string(this->unique_id()) + ")";
160 }
161
162 gr::io_signature::sptr input_signature() const { return d_input_signature; }
163 gr::io_signature::sptr output_signature() const { return d_output_signature; }
164 basic_block_sptr to_basic_block(); // Needed for Python type coercion
165
166 /*!
167 * True if the block has an alias (see set_block_alias).
168 */
169 bool alias_set() const { return !d_symbol_alias.empty(); }
170
171 /*!
172 * Returns the block's alias as a string.
173 */
174 std::string alias() const { return alias_set() ? d_symbol_alias : symbol_name(); }
175
176 /*!
177 * Returns the block's alias as PMT.
178 */
179 pmt::pmt_t alias_pmt() const { return pmt::intern(alias()); }
180
181 /*!
182 * Set's a new alias for the block; also adds an entry into the
183 * block_registry to get the block using either the alias or the
184 * original symbol name.
185 */
186 void set_block_alias(std::string name);
187
188 // ** Message passing interface **
194
195 virtual bool message_port_is_hier(pmt::pmt_t port_id)
196 {
197 (void)port_id;
198 return false;
199 }
201 {
202 (void)port_id;
203 return false;
204 }
206 {
207 (void)port_id;
208 return false;
209 }
210
211 /*!
212 * \brief Get input message port names.
213 *
214 * Returns the available input message ports for a block. The
215 * return object is a PMT vector that is filled with PMT symbols.
216 */
218
219 /*!
220 * \brief Get output message port names.
221 *
222 * Returns the available output message ports for a block. The
223 * return object is a PMT vector that is filled with PMT symbols.
224 */
226
227 /*!
228 * Accept msg, place in queue, arrange for thread to be awakened if it's not already.
229 */
230 void _post(pmt::pmt_t which_port, pmt::pmt_t msg);
231
232 //! is the queue empty?
233 bool empty_p(pmt::pmt_t which_port)
234 {
235 if (msg_queue.find(which_port) == msg_queue.end())
236 throw std::runtime_error("port does not exist!");
237 return msg_queue[which_port].empty();
238 }
239 bool empty_p()
240 {
241 bool rv = true;
242 for (const auto& i : msg_queue) {
243 rv &= msg_queue[i.first].empty();
244 }
245 return rv;
246 }
247
248 //! are all msg ports with handlers empty?
250 {
251 return (empty_p(which_port) || !has_msg_handler(which_port));
252 }
254 {
255 bool rv = true;
256 for (const auto& i : msg_queue) {
257 rv &= empty_handled_p(i.first);
258 }
259 return rv;
260 }
261
262 //! How many messages in the queue?
263 size_t nmsgs(pmt::pmt_t which_port)
264 {
265 if (msg_queue.find(which_port) == msg_queue.end())
266 throw std::runtime_error("port does not exist!");
267 return msg_queue[which_port].size();
268 }
269
270 //| Acquires and release the mutex
272 /*!
273 * \returns returns pmt at head of queue or pmt::pmt_t() if empty.
274 */
276
277 msg_queue_t::iterator get_iterator(pmt::pmt_t which_port)
278 {
279 return msg_queue[which_port].begin();
280 }
281
282 void erase_msg(pmt::pmt_t which_port, msg_queue_t::iterator it)
283 {
284 msg_queue[which_port].erase(it);
285 }
286
287 virtual bool has_msg_port(pmt::pmt_t which_port)
288 {
289 if (msg_queue.find(which_port) != msg_queue.end()) {
290 return true;
291 }
292 if (pmt::dict_has_key(d_message_subscribers, which_port)) {
293 return true;
294 }
295 return false;
296 }
297
298 const msg_queue_map_t& get_msg_map(void) const { return msg_queue; }
299
300#ifdef GR_CTRLPORT
301 /*!
302 * \brief Add an RPC variable (get or set).
303 *
304 * Using controlport, we create new getters/setters and need to
305 * store them. Each block has a vector to do this, and these never
306 * need to be accessed again once they are registered with the RPC
307 * backend. This function takes a
308 * std::shared_sptr<rpcbasic_base> so that when the block is
309 * deleted, all RPC registered variables are cleaned up.
310 *
311 * \param s an rpcbasic_sptr of the new RPC variable register to store.
312 */
313 void add_rpc_variable(rpcbasic_sptr s) { d_rpc_vars.push_back(s); }
314#endif /* GR_CTRLPORT */
315
316 /*!
317 * \brief Set up the RPC registered variables.
318 *
319 * This must be overloaded by a block that wants to use
320 * controlport. This is where rpcbasic_register_{get,set} pointers
321 * are created, which then get wrapped as shared pointers
322 * (rpcbasic_sptr(...)) and stored using add_rpc_variable.
323 */
324 virtual void setup_rpc(){};
325
326 /*!
327 * \brief Ask if this block has been registered to the RPC.
328 *
329 * We can only register a block once, so we use this to protect us
330 * from calling it multiple times.
331 */
332 bool is_rpc_set() { return d_rpc_set; }
333
334 /*!
335 * \brief When the block is registered with the RPC, set this.
336 */
337 void rpc_set() { d_rpc_set = true; }
338
339 /*!
340 * \brief Confirm that ninputs and noutputs is an acceptable combination.
341 *
342 * \param ninputs number of input streams connected
343 * \param noutputs number of output streams connected
344 *
345 * \returns true if this is a valid configuration for this block.
346 *
347 * This function is called by the runtime system whenever the
348 * topology changes. Most classes do not need to override this.
349 * This check is in addition to the constraints specified by the
350 * input and output gr::io_signatures.
351 */
352 virtual bool check_topology(int ninputs, int noutputs)
353 {
354 (void)ninputs;
355 (void)noutputs;
356 return true;
357 }
358
359 /*!
360 * \brief Set the callback that is fired when messages are available.
361 *
362 * \p msg_handler can be any kind of function pointer or function object
363 * that has the signature:
364 * <pre>
365 * void msg_handler(pmt::pmt msg);
366 * </pre>
367 *
368 * (You may want to use boost::bind to massage your callable into
369 * the correct form. See gr::blocks::nop for an example that sets
370 * up a class method as the callback.)
371 *
372 * Blocks that desire to handle messages must call this method in
373 * their constructors to register the handler that will be invoked
374 * when messages are available.
375 *
376 * If the block inherits from block, the runtime system will
377 * ensure that msg_handler is called in a thread-safe manner, such
378 * that work and msg_handler will never be called concurrently.
379 * This allows msg_handler to update state variables without
380 * having to worry about thread-safety issues with work,
381 * general_work or another invocation of msg_handler.
382 *
383 * If the block inherits from hier_block2, the runtime system
384 * will ensure that no reentrant calls are made to msg_handler.
385 */
386 template <typename T>
388 {
389 if (msg_queue.find(which_port) == msg_queue.end()) {
390 throw std::runtime_error(
391 "attempt to set_msg_handler() on bad input message port!");
392 }
393 d_msg_handlers[which_port] = msg_handler_t(msg_handler);
394 }
395
396 virtual void set_processor_affinity(const std::vector<int>& mask) = 0;
397
398 virtual void unset_processor_affinity() = 0;
399
400 virtual std::vector<int> processor_affinity() = 0;
401
402 virtual void set_log_level(const std::string& level) = 0;
403
404 virtual std::string log_level() = 0;
405};
406
407inline bool operator<(basic_block_sptr lhs, basic_block_sptr rhs)
408{
409 return lhs->unique_id() < rhs->unique_id();
410}
411
412typedef std::vector<basic_block_sptr> basic_block_vector_t;
413typedef std::vector<basic_block_sptr>::iterator basic_block_viter_t;
414
416
417inline std::ostream& operator<<(std::ostream& os, basic_block_sptr basic_block)
418{
419 os << basic_block->identifier();
420 return os;
421}
422
423} /* namespace gr */
424
425#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:162
virtual void set_log_level(const std::string &level)=0
bool empty_handled_p(pmt::pmt_t which_port)
are all msg ports with handlers empty?
Definition: basic_block.h:249
bool is_rpc_set()
Ask if this block has been registered to the RPC.
Definition: basic_block.h:332
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:205
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:145
const msg_queue_map_t & get_msg_map(void) const
Definition: basic_block.h:298
msg_queue_t::iterator get_iterator(pmt::pmt_t which_port)
Definition: basic_block.h:277
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:263
virtual void set_processor_affinity(const std::vector< int > &mask)=0
std::shared_ptr< Derived > shared_from_base()
This is meant to be called by derived classes (e.g. block) to get a shared pointer internally....
Definition: basic_block.h:137
virtual bool message_port_is_hier_in(pmt::pmt_t port_id)
Definition: basic_block.h:200
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:253
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:157
long symbolic_id() const
Definition: basic_block.h:146
pmt::pmt_t alias_pmt() const
Definition: basic_block.h:179
virtual void setup_rpc()
Set up the RPC registered variables.
Definition: basic_block.h:324
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:387
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:195
long d_unique_id
Definition: basic_block.h:68
virtual bool has_msg_port(pmt::pmt_t which_port)
Definition: basic_block.h:287
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:156
std::string alias() const
Definition: basic_block.h:174
void _post(pmt::pmt_t which_port, pmt::pmt_t msg)
bool alias_set() const
Definition: basic_block.h:169
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:337
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:352
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:282
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)
gr::io_signature::sptr output_signature() const
Definition: basic_block.h:163
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:233
bool empty_p()
Definition: basic_block.h:239
pmt::pmt_t d_message_subscribers
Definition: basic_block.h:128
std::string name() const
Definition: basic_block.h:149
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:150
std::shared_ptr< io_signature > sptr
Definition: io_signature.h:40
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
GR_RUNTIME_API const pmt::pmt_t msg()
boost::mutex mutex
Definition: thread.h:37
GNU Radio logging wrapper.
Definition: basic_block.h:29
std::shared_ptr< logger > logger_ptr
Definition: logger.h:208
std::vector< basic_block_sptr > basic_block_vector_t
Definition: basic_block.h:412
std::ostream & operator<<(std::ostream &os, basic_block_sptr basic_block)
Definition: basic_block.h:417
bool operator<(basic_block_sptr lhs, basic_block_sptr rhs)
Definition: basic_block.h:407
std::vector< basic_block_sptr >::iterator basic_block_viter_t
Definition: basic_block.h:413
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