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