GNU Radio C++ API Reference  gcd20ee2
The Free & Open Software Radio Ecosystem
buffer.h
Go to the documentation of this file.
1 /* -*- c++ -*- */
2 /*
3  * Copyright 2004,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_RUNTIME_BUFFER_H
12 #define INCLUDED_GR_RUNTIME_BUFFER_H
13 
14 #include <gnuradio/api.h>
15 #include <gnuradio/buffer_type.h>
16 #include <gnuradio/custom_lock.h>
17 #include <gnuradio/logger.h>
18 #include <gnuradio/runtime_types.h>
19 #include <gnuradio/tags.h>
20 #include <gnuradio/thread/thread.h>
21 #include <gnuradio/transfer_type.h>
22 
23 #include <functional>
24 #include <iostream>
25 #include <map>
26 #include <memory>
27 
28 
29 namespace gr {
30 
31 class vmcircbuf;
32 class buffer_reader;
33 class buffer_reader_sm;
34 
36 
37 typedef std::function<void*(void*, const void*, std::size_t)> mem_func_t;
38 
39 /*!
40  * \brief Allocate a buffer that holds at least \p nitems of size \p sizeof_item.
41  *
42  * The total size of the buffer will be rounded up to a system
43  * dependent boundary. This is typically the system page size, but
44  * under MS windows is 64KB.
45  *
46  * \param nitems is the minimum number of items the buffer will hold.
47  * \param sizeof_item is the size of an item in bytes.
48  * \param downstream_lcm_nitems is the least common multiple of the items to
49  * read by downstream block(s)
50  * \param downstream_max_out_mult is the maximum output multiple of all
51  * downstream blocks
52  * \param link is the block that writes to this buffer.
53  * \param buf_owner is the block that owns the buffer which may or may not
54  * be the same as the block that writes to this buffer
55  */
56 GR_RUNTIME_API buffer_sptr make_buffer(int nitems,
57  size_t sizeof_item,
58  uint64_t downstream_lcm_nitems,
59  uint32_t downstream_max_out_mult,
60  block_sptr link = block_sptr(),
61  block_sptr buf_owner = block_sptr());
62 
63 /*!
64  * \brief Single writer, multiple reader fifo.
65  * \ingroup internal
66  */
68 {
69 public:
72 
73  ~buffer() override;
74 
75  /*!
76  * \brief return the buffer's mapping type
77  */
78  buffer_mapping_type get_mapping_type() { return d_buf_map_type; }
79 
80  /*!
81  * \brief return the buffer's buffer_type
82  */
83  virtual buffer_type get_buffer_type() const = 0;
84 
85  /*!
86  * \brief return number of items worth of space available for writing
87  */
88  virtual int space_available() = 0;
89 
90  /*!
91  * \brief return size of this buffer in items
92  */
93  unsigned int bufsize() const { return d_bufsize; }
94 
95  /*!
96  * \brief return the base address of the buffer
97  */
98  const char* base() const { return static_cast<const char*>(d_base); }
99 
100  /*!
101  * \brief return pointer to write buffer.
102  *
103  * The return value points at space that can hold at least
104  * space_available() items.
105  */
106  virtual void* write_pointer();
107 
108  /*!
109  * \brief return pointer to read buffer.
110  *
111  * The return value points to at least items_available() items.
112  */
113  virtual const void* _read_pointer(unsigned int read_index);
114 
115  /*!
116  * \brief tell buffer that we wrote \p nitems into it
117  */
118  void update_write_pointer(int nitems);
119 
120  void set_done(bool done);
121  bool done() const { return d_done; }
122 
123  /*!
124  * \brief Return the block that writes to this buffer.
125  */
126  block_sptr link() { return block_sptr(d_link); }
127 
128  size_t nreaders() const { return d_readers.size(); }
129  buffer_reader* reader(size_t index) { return d_readers[index]; }
130 
131  gr::thread::mutex* mutex() { return &d_mutex; }
132 
133  uint64_t nitems_written() { return d_abs_write_offset; }
134 
136  {
137  d_write_index = 0;
138  d_abs_write_offset = 0;
139  }
140 
141  size_t get_sizeof_item() { return d_sizeof_item; }
142 
143  uint64_t get_downstream_lcm_nitems() { return d_downstream_lcm_nitems; }
144 
145  uint32_t get_max_reader_output_multiple() { return d_max_reader_output_multiple; }
146 
147  virtual void update_reader_block_history(unsigned history, int delay)
148  {
149  d_max_reader_history = std::max(d_max_reader_history, history);
150  d_has_history = (d_max_reader_history > 1);
151  }
152 
153  /*!
154  * \brief Adds a new tag to the buffer.
155  *
156  * \param tag the new tag
157  */
158  void add_item_tag(const tag_t& tag);
159 
160  /*!
161  * \brief Removes all tags before \p max_time from buffer
162  *
163  * \param max_time the time (item number) to trim up until.
164  */
165  void prune_tags(uint64_t max_time);
166 
167  std::multimap<uint64_t, tag_t>::iterator get_tags_begin()
168  {
169  return d_item_tags.begin();
170  }
171  std::multimap<uint64_t, tag_t>::iterator get_tags_end() { return d_item_tags.end(); }
172  std::multimap<uint64_t, tag_t>::iterator get_tags_lower_bound(uint64_t x)
173  {
174  return d_item_tags.lower_bound(x);
175  }
176  std::multimap<uint64_t, tag_t>::iterator get_tags_upper_bound(uint64_t x)
177  {
178  return d_item_tags.upper_bound(x);
179  }
180 
181  /*!
182  * \brief Function to be executed after this object's owner completes the
183  * call to general_work()
184  */
185  virtual void post_work(int nitems) = 0;
186 
187  /*!
188  * \brief Returns true when the current thread is ready to call the callback,
189  * false otherwise. Note if input_blocked_callback is overridden then this
190  * function should also be overridden.
191  */
192  virtual bool input_blkd_cb_ready( int items_required,
193  unsigned read_index)
194  {
195  return false;
196  }
197 
198  /*!
199  * \brief Callback function that the scheduler will call when it determines
200  * that the input is blocked. Override this function if needed.
201  */
202  virtual bool input_blocked_callback( int items_required,
203  int items_avail,
204  unsigned read_index)
205  {
206  return false;
207  }
208 
209  /*!
210  * \brief Returns true if the current thread is ready to execute
211  * output_blocked_callback(), false otherwise. Note if the default
212  * output_blocked_callback is overridden this function should also be
213  * overridden.
214  */
215  virtual bool output_blkd_cb_ready( int output_multiple)
216  {
217  return false;
218  }
219 
220  /*!
221  * \brief Callback function that the scheduler will call when it determines
222  * that the output is blocked. Override this function if needed.
223  */
224  virtual bool output_blocked_callback( int output_multiple,
225  bool force = false)
226  {
227  return false;
228  }
229 
230  /*!
231  * \brief Increment the number of active pointers for this buffer.
232  */
233  inline void increment_active()
234  {
235  gr::thread::scoped_lock lock(d_mutex);
236 
237  d_cv.wait(lock, [this]() { return d_callback_flag == false; });
238  ++d_active_pointer_counter;
239  }
240 
241  /*!
242  * \brief Decrement the number of active pointers for this buffer and signal
243  * anyone waiting when the count reaches zero.
244  */
245  inline void decrement_active()
246  {
247  gr::thread::scoped_lock lock(d_mutex);
248 
249  if (--d_active_pointer_counter == 0)
250  d_cv.notify_all();
251  }
252 
253  /*!
254  * \brief "on_lock" function from the custom_lock_if.
255  */
256  void on_lock(gr::thread::scoped_lock& lock) override;
257 
258  /*!
259  * \brief "on_unlock" function from the custom_lock_if.
260  */
261  void on_unlock() override;
262 
263  friend std::ostream& operator<<(std::ostream& os, const buffer& buf);
264 
265  // -------------------------------------------------------------------------
266 
267  /*!
268  * \brief Create a buffer_reader for this buffer.
269  *
270  * Derived buffer classes can override this to return a custom
271  * reader type (e.g. one that adds post-consumption signalling).
272  * The default implementation returns buffer_reader for double-mapped
273  * buffers and buffer_reader_sm for single-mapped buffers.
274  */
275  virtual buffer_reader_sptr
276  create_reader(buffer_sptr buf, int nzero_preload, block_sptr link, int delay);
277 
278  /*!
279  * \brief Assign buffer's transfer_type
280  */
281  void set_transfer_type(const transfer_type& type);
282 
283 protected:
284  /*!
285  * \brief Called after the transfer type has been successfully assigned.
286  *
287  * Derived buffer classes can override this to perform deferred
288  * allocation or configuration that depends on the transfer type.
289  * For example, a GPU buffer may skip host-side memory allocation
290  * for DEVICE_TO_DEVICE edges.
291  *
292  * The default implementation is a no-op.
293  */
294  virtual void on_transfer_type_set(const transfer_type& /* type */) {}
295 
296 private:
297  friend class buffer_reader;
298  friend class buffer_reader_sm;
299 
300  friend GR_RUNTIME_API buffer_sptr make_buffer(int nitems,
301  size_t sizeof_item,
302  uint64_t downstream_lcm_nitems,
303  block_sptr link);
304  friend GR_RUNTIME_API buffer_reader_sptr buffer_add_reader(buffer_sptr buf,
305  int nzero_preload,
306  block_sptr link,
307  int delay);
308 
309 protected:
310  char* d_base; // base address of buffer inside d_vmcircbuf.
311  unsigned int d_bufsize; // in items
313 
314  // Keep track of maximum sample delay of any reader; Only prune tags past this.
316 
317  // Keep track of the maximum sample history requirements of all blocks that
318  // consume from this buffer
320 
321  // Indicates if d_max_reader_history > 1
323 
324  size_t d_sizeof_item; // in bytes
325  std::vector<buffer_reader*> d_readers;
326  std::weak_ptr<block> d_link; // block that writes to this buffer
327 
328  //
329  // The mutex protects d_write_index, d_abs_write_offset, d_done, d_item_tags
330  // and the d_read_index's and d_abs_read_offset's in the buffer readers.
331  // Also d_callback_flag and d_active_pointer_counter.
332  //
334  unsigned int d_write_index; // in items [0,d_bufsize)
335  uint64_t d_abs_write_offset; // num items written since the start
336  bool d_done;
337  std::multimap<uint64_t, tag_t> d_item_tags;
339  //
343 
347 
349 
350  /*!
351  * \brief Increment read or write index for this buffer
352  */
353  virtual unsigned index_add(unsigned a, unsigned b) = 0;
354 
355  /*!
356  * \brief Decrement read or write index for this buffer
357  */
358  virtual unsigned index_sub(unsigned a, unsigned b) = 0;
359 
360  virtual bool allocate_buffer( int nitems) { return false; };
361 
362  /*!
363  * \brief constructor is private. Use gr_make_buffer to create instances.
364  *
365  * Allocate a buffer that holds at least \p nitems of size \p sizeof_item.
366  *
367  * \param buftype is an enum type that describes the buffer TODO: fix me
368  * \param nitems is the minimum number of items the buffer will hold.
369  * \param sizeof_item is the size of an item in bytes.
370  * \param downstream_lcm_nitems is the least common multiple of the items to
371  * read by downstream block(s)
372  * \param downstream_max_out_mult is the maximum output multiple of all
373  * downstream blocks
374  * \param link is the block that writes to this buffer.
375  *
376  * The total size of the buffer will be rounded up to a system
377  * dependent boundary. This is typically the system page size, but
378  * under MS windows is 64KB.
379  */
381  int nitems,
382  size_t sizeof_item,
383  uint64_t downstream_lcm_nitems,
384  uint32_t downstream_max_out_mult,
385  block_sptr link);
386 
387  /*!
388  * \brief disassociate \p reader from this buffer
389  */
390  void drop_reader(buffer_reader* reader);
391 };
392 
393 //! returns # of buffers currently allocated
395 
396 } /* namespace gr */
397 
398 #endif /* INCLUDED_GR_RUNTIME_BUFFER_H */
Definition: buffer_reader_sm.h:22
How we keep track of the readers of a gr::buffer.
Definition: buffer_reader.h:53
Base class for describing a buffer's type.
Definition: buffer_type.h:28
Single writer, multiple reader fifo.
Definition: buffer.h:68
uint32_t d_active_pointer_counter
Definition: buffer.h:342
size_t nreaders() const
Definition: buffer.h:128
unsigned d_max_reader_delay
Definition: buffer.h:315
gr::thread::mutex d_mutex
Definition: buffer.h:333
std::weak_ptr< block > d_link
Definition: buffer.h:326
const char * base() const
return the base address of the buffer
Definition: buffer.h:98
buffer_reader * reader(size_t index)
Definition: buffer.h:129
uint64_t get_downstream_lcm_nitems()
Definition: buffer.h:143
uint64_t d_write_multiple
Definition: buffer.h:345
void prune_tags(uint64_t max_time)
Removes all tags before max_time from buffer.
virtual bool allocate_buffer(int nitems)
Definition: buffer.h:360
bool done() const
Definition: buffer.h:121
void decrement_active()
Decrement the number of active pointers for this buffer and signal anyone waiting when the count reac...
Definition: buffer.h:245
void increment_active()
Increment the number of active pointers for this buffer.
Definition: buffer.h:233
void add_item_tag(const tag_t &tag)
Adds a new tag to the buffer.
virtual void post_work(int nitems)=0
Function to be executed after this object's owner completes the call to general_work()
virtual buffer_reader_sptr create_reader(buffer_sptr buf, int nzero_preload, block_sptr link, int delay)
Create a buffer_reader for this buffer.
gr::logger_ptr d_logger
Definition: buffer.h:70
gr::thread::mutex * mutex()
Definition: buffer.h:131
virtual unsigned index_add(unsigned a, unsigned b)=0
Increment read or write index for this buffer.
virtual bool output_blkd_cb_ready(int output_multiple)
Returns true if the current thread is ready to execute output_blocked_callback(), false otherwise....
Definition: buffer.h:215
friend GR_RUNTIME_API buffer_sptr make_buffer(int nitems, size_t sizeof_item, uint64_t downstream_lcm_nitems, block_sptr link)
unsigned int d_bufsize
Definition: buffer.h:311
std::multimap< uint64_t, tag_t >::iterator get_tags_upper_bound(uint64_t x)
Definition: buffer.h:176
virtual bool input_blocked_callback(int items_required, int items_avail, unsigned read_index)
Callback function that the scheduler will call when it determines that the input is blocked....
Definition: buffer.h:202
virtual bool output_blocked_callback(int output_multiple, bool force=false)
Callback function that the scheduler will call when it determines that the output is blocked....
Definition: buffer.h:224
std::multimap< uint64_t, tag_t >::iterator get_tags_lower_bound(uint64_t x)
Definition: buffer.h:172
uint32_t d_max_reader_output_multiple
Definition: buffer.h:346
virtual void * write_pointer()
return pointer to write buffer.
~buffer() override
virtual const void * _read_pointer(unsigned int read_index)
return pointer to read buffer.
void reset_nitem_counter()
Definition: buffer.h:135
void on_unlock() override
"on_unlock" function from the custom_lock_if.
uint64_t d_abs_write_offset
Definition: buffer.h:335
buffer_mapping_type d_buf_map_type
Definition: buffer.h:312
friend std::ostream & operator<<(std::ostream &os, const buffer &buf)
uint32_t get_max_reader_output_multiple()
Definition: buffer.h:145
bool d_has_history
Definition: buffer.h:322
virtual int space_available()=0
return number of items worth of space available for writing
void set_done(bool done)
void drop_reader(buffer_reader *reader)
disassociate reader from this buffer
virtual bool input_blkd_cb_ready(int items_required, unsigned read_index)
Returns true when the current thread is ready to call the callback, false otherwise....
Definition: buffer.h:192
block_sptr link()
Return the block that writes to this buffer.
Definition: buffer.h:126
buffer_mapping_type get_mapping_type()
return the buffer's mapping type
Definition: buffer.h:78
virtual void update_reader_block_history(unsigned history, int delay)
Definition: buffer.h:147
void set_transfer_type(const transfer_type &type)
Assign buffer's transfer_type.
size_t get_sizeof_item()
Definition: buffer.h:141
unsigned int bufsize() const
return size of this buffer in items
Definition: buffer.h:93
uint64_t d_downstream_lcm_nitems
Definition: buffer.h:344
std::multimap< uint64_t, tag_t > d_item_tags
Definition: buffer.h:337
std::vector< buffer_reader * > d_readers
Definition: buffer.h:325
friend GR_RUNTIME_API buffer_reader_sptr buffer_add_reader(buffer_sptr buf, int nzero_preload, block_sptr link, int delay)
Create a new gr::buffer_reader and attach it to buffer buf.
void on_lock(gr::thread::scoped_lock &lock) override
"on_lock" function from the custom_lock_if.
unsigned d_max_reader_history
Definition: buffer.h:319
void update_write_pointer(int nitems)
tell buffer that we wrote nitems into it
bool d_done
Definition: buffer.h:336
unsigned int d_write_index
Definition: buffer.h:334
char * d_base
Definition: buffer.h:310
virtual unsigned index_sub(unsigned a, unsigned b)=0
Decrement read or write index for this buffer.
uint64_t nitems_written()
Definition: buffer.h:133
size_t d_sizeof_item
Definition: buffer.h:324
buffer(buffer_mapping_type buftype, int nitems, size_t sizeof_item, uint64_t downstream_lcm_nitems, uint32_t downstream_max_out_mult, block_sptr link)
constructor is private. Use gr_make_buffer to create instances.
std::multimap< uint64_t, tag_t >::iterator get_tags_end()
Definition: buffer.h:171
virtual void on_transfer_type_set(const transfer_type &)
Called after the transfer type has been successfully assigned.
Definition: buffer.h:294
virtual buffer_type get_buffer_type() const =0
return the buffer's buffer_type
transfer_type d_transfer_type
Definition: buffer.h:348
gr::thread::condition_variable d_cv
Definition: buffer.h:340
std::multimap< uint64_t, tag_t >::iterator get_tags_begin()
Definition: buffer.h:167
gr::logger_ptr d_debug_logger
Definition: buffer.h:71
uint64_t d_last_min_items_read
Definition: buffer.h:338
bool d_callback_flag
Definition: buffer.h:341
Definition: custom_lock.h:27
#define GR_RUNTIME_API
Definition: gnuradio-runtime/include/gnuradio/api.h:18
boost::mutex mutex
Definition: thread.h:34
boost::unique_lock< boost::mutex > scoped_lock
Definition: thread.h:35
boost::condition_variable condition_variable
Definition: thread.h:36
GNU Radio logging wrapper.
Definition: basic_block.h:29
std::function< void *(void *, const void *, std::size_t)> mem_func_t
Definition: buffer.h:37
std::shared_ptr< logger > logger_ptr
Definition: logger.h:248
GR_RUNTIME_API buffer_sptr make_buffer(int nitems, size_t sizeof_item, uint64_t downstream_lcm_nitems, uint32_t downstream_max_out_mult, block_sptr link=block_sptr(), block_sptr buf_owner=block_sptr())
Allocate a buffer that holds at least nitems of size sizeof_item.
transfer_type
Definition: transfer_type.h:19
buffer_mapping_type
Definition: buffer.h:35
GR_RUNTIME_API long buffer_ncurrently_allocated()
returns # of buffers currently allocated
Template used to create buffer types. Note that the factory_class parameter must contain a static fun...
Definition: buffer_type.h:94
Definition: tags.h:28