GNU Radio Manual and C++ API Reference  v3.9.2.0-89-gb7c7001e
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/logger.h>
16 #include <gnuradio/runtime_types.h>
17 #include <gnuradio/tags.h>
18 #include <gnuradio/thread/thread.h>
19 #include <boost/weak_ptr.hpp>
20 #include <map>
21 #include <memory>
22 
23 namespace gr {
24 
25 class vmcircbuf;
26 
27 /*!
28  * \brief Allocate a buffer that holds at least \p nitems of size \p sizeof_item.
29  *
30  * The total size of the buffer will be rounded up to a system
31  * dependent boundary. This is typically the system page size, but
32  * under MS windows is 64KB.
33  *
34  * \param nitems is the minimum number of items the buffer will hold.
35  * \param sizeof_item is the size of an item in bytes.
36  * \param link is the block that writes to this buffer.
37  */
38 GR_RUNTIME_API buffer_sptr make_buffer(int nitems,
39  size_t sizeof_item,
40  block_sptr link = block_sptr());
41 
42 /*!
43  * \brief Single writer, multiple reader fifo.
44  * \ingroup internal
45  */
47 {
48 public:
51 
52  virtual ~buffer();
53 
54  /*!
55  * \brief return number of items worth of space available for writing
56  */
58 
59  /*!
60  * \brief return size of this buffer in items
61  */
62  int bufsize() const { return d_bufsize; }
63 
64  /*!
65  * \brief return the base address of the buffer
66  */
67  const char* base() const { return static_cast<const char*>(d_base); }
68 
69  /*!
70  * \brief return pointer to write buffer.
71  *
72  * The return value points at space that can hold at least
73  * space_available() items.
74  */
75  void* write_pointer();
76 
77  /*!
78  * \brief tell buffer that we wrote \p nitems into it
79  */
80  void update_write_pointer(int nitems);
81 
82  void set_done(bool done);
83  bool done() const { return d_done; }
84 
85  /*!
86  * \brief Return the block that writes to this buffer.
87  */
88  block_sptr link() { return block_sptr(d_link); }
89 
90  size_t nreaders() const { return d_readers.size(); }
91  buffer_reader* reader(size_t index) { return d_readers[index]; }
92 
93  gr::thread::mutex* mutex() { return &d_mutex; }
94 
95  uint64_t nitems_written() { return d_abs_write_offset; }
96 
97  void reset_nitem_counter() { d_abs_write_offset = 0; }
98 
99  size_t get_sizeof_item() { return d_sizeof_item; }
100 
101  /*!
102  * \brief Adds a new tag to the buffer.
103  *
104  * \param tag the new tag
105  */
106  void add_item_tag(const tag_t& tag);
107 
108  /*!
109  * \brief Removes an existing tag from the buffer.
110  *
111  * If no such tag is found, does nothing.
112  * Note: Doesn't actually physically delete the tag, but
113  * marks it as deleted. For the user, this has the same effect:
114  * Any subsequent calls to get_tags_in_range() will not return
115  * the tag.
116  *
117  * \param tag the tag that needs to be removed
118  * \param id the unique ID of the block calling this function
119  */
120  void remove_item_tag(const tag_t& tag, long id);
121 
122  /*!
123  * \brief Removes all tags before \p max_time from buffer
124  *
125  * \param max_time the time (item number) to trim up until.
126  */
127  void prune_tags(uint64_t max_time);
128 
129  std::multimap<uint64_t, tag_t>::iterator get_tags_begin()
130  {
131  return d_item_tags.begin();
132  }
133  std::multimap<uint64_t, tag_t>::iterator get_tags_end() { return d_item_tags.end(); }
134  std::multimap<uint64_t, tag_t>::iterator get_tags_lower_bound(uint64_t x)
135  {
136  return d_item_tags.lower_bound(x);
137  }
138  std::multimap<uint64_t, tag_t>::iterator get_tags_upper_bound(uint64_t x)
139  {
140  return d_item_tags.upper_bound(x);
141  }
142 
143  // -------------------------------------------------------------------------
144 
145 private:
146  friend class buffer_reader;
147  friend GR_RUNTIME_API buffer_sptr make_buffer(int nitems,
148  size_t sizeof_item,
149  block_sptr link);
150  friend GR_RUNTIME_API buffer_reader_sptr buffer_add_reader(buffer_sptr buf,
151  int nzero_preload,
152  block_sptr link,
153  int delay);
154 
155 protected:
156  char* d_base; // base address of buffer inside d_vmcircbuf.
157  unsigned int d_bufsize; // in items
158 
159  // Keep track of maximum sample delay of any reader; Only prune tags past this.
161 
162 private:
163  std::unique_ptr<gr::vmcircbuf> d_vmcircbuf;
164  size_t d_sizeof_item; // in bytes
165  std::vector<buffer_reader*> d_readers;
166  std::weak_ptr<block> d_link; // block that writes to this buffer
167 
168  //
169  // The mutex protects d_write_index, d_abs_write_offset, d_done, d_item_tags
170  // and the d_read_index's and d_abs_read_offset's in the buffer readers.
171  //
172  gr::thread::mutex d_mutex;
173  unsigned int d_write_index; // in items [0,d_bufsize)
174  uint64_t d_abs_write_offset; // num items written since the start
175  bool d_done;
176  std::multimap<uint64_t, tag_t> d_item_tags;
177  uint64_t d_last_min_items_read;
178 
179  unsigned index_add(unsigned a, unsigned b)
180  {
181  unsigned s = a + b;
182 
183  if (s >= d_bufsize)
184  s -= d_bufsize;
185 
186  assert(s < d_bufsize);
187  return s;
188  }
189 
190  unsigned index_sub(unsigned a, unsigned b)
191  {
192  int s = a - b;
193 
194  if (s < 0)
195  s += d_bufsize;
196 
197  assert((unsigned)s < d_bufsize);
198  return s;
199  }
200 
201  virtual bool allocate_buffer(int nitems, size_t sizeof_item);
202 
203  /*!
204  * \brief constructor is private. Use gr_make_buffer to create instances.
205  *
206  * Allocate a buffer that holds at least \p nitems of size \p sizeof_item.
207  *
208  * \param nitems is the minimum number of items the buffer will hold.
209  * \param sizeof_item is the size of an item in bytes.
210  * \param link is the block that writes to this buffer.
211  *
212  * The total size of the buffer will be rounded up to a system
213  * dependent boundary. This is typically the system page size, but
214  * under MS windows is 64KB.
215  */
216  buffer(int nitems, size_t sizeof_item, block_sptr link);
217 
218  /*!
219  * \brief disassociate \p reader from this buffer
220  */
221  void drop_reader(buffer_reader* reader);
222 };
223 
224 /*!
225  * \brief Create a new gr::buffer_reader and attach it to buffer \p buf
226  * \param buf is the buffer the \p gr::buffer_reader reads from.
227  * \param nzero_preload -- number of zero items to "preload" into buffer.
228  * \param link is the block that reads from the buffer using this gr::buffer_reader.
229  * \param delay Optional setting to declare the buffer's sample delay.
230  */
231 GR_RUNTIME_API buffer_reader_sptr buffer_add_reader(buffer_sptr buf,
232  int nzero_preload,
233  block_sptr link = block_sptr(),
234  int delay = 0);
235 
236 //! returns # of buffers currently allocated
238 
239 
240 // ---------------------------------------------------------------------------
241 
242 /*!
243  * \brief How we keep track of the readers of a gr::buffer.
244  * \ingroup internal
245  */
247 {
248 public:
250 
251  /*!
252  * Declares the sample delay for this reader.
253  *
254  * See gr::block::declare_sample_delay for details.
255  *
256  * \param delay The new sample delay
257  */
258  void declare_sample_delay(unsigned delay);
259 
260  /*!
261  * Gets the sample delay for this reader.
262  *
263  * See gr::block::sample_delay for details.
264  */
265  unsigned sample_delay() const;
266 
267  /*!
268  * \brief Return number of items available for reading.
269  */
270  int items_available() const;
271 
272  /*!
273  * \brief Return buffer this reader reads from.
274  */
275  buffer_sptr buffer() const { return d_buffer; }
276 
277  /*!
278  * \brief Return maximum number of items that could ever be available for reading.
279  * This is used as a sanity check in the scheduler to avoid looping forever.
280  */
281  int max_possible_items_available() const { return d_buffer->d_bufsize - 1; }
282 
283  /*!
284  * \brief return pointer to read buffer.
285  *
286  * The return value points to items_available() number of items
287  */
288  const void* read_pointer();
289 
290  /*
291  * \brief tell buffer we read \p items from it
292  */
293  void update_read_pointer(int nitems);
294 
295  void set_done(bool done) { d_buffer->set_done(done); }
296  bool done() const { return d_buffer->done(); }
297 
298  gr::thread::mutex* mutex() { return d_buffer->mutex(); }
299 
300  uint64_t nitems_read() { return d_abs_read_offset; }
301 
302  void reset_nitem_counter() { d_abs_read_offset = 0; }
303 
304  size_t get_sizeof_item() { return d_buffer->get_sizeof_item(); }
305 
306  /*!
307  * \brief Return the block that reads via this reader.
308  *
309  */
310  block_sptr link() { return block_sptr(d_link); }
311 
312  /*!
313  * \brief Given a [start,end), returns a vector all tags in the range.
314  *
315  * Get a vector of tags in given range. Range of counts is from start to end-1.
316  *
317  * Tags are tuples of:
318  * (item count, source id, key, value)
319  *
320  * \param v a vector reference to return tags into
321  * \param abs_start a uint64 count of the start of the range of interest
322  * \param abs_end a uint64 count of the end of the range of interest
323  * \param id the unique ID of the block to make sure already deleted tags
324  * are not returned
325  */
326  void get_tags_in_range(std::vector<tag_t>& v,
327  uint64_t abs_start,
328  uint64_t abs_end,
329  long id);
330 
331  // -------------------------------------------------------------------------
332 
333 private:
334  friend class buffer;
335  friend GR_RUNTIME_API buffer_reader_sptr buffer_add_reader(buffer_sptr buf,
336  int nzero_preload,
337  block_sptr link,
338  int delay);
339 
340  buffer_sptr d_buffer;
341  unsigned int d_read_index; // in items [0,d->buffer.d_bufsize)
342  uint64_t d_abs_read_offset; // num items seen since the start
343  std::weak_ptr<block> d_link; // block that reads via this buffer reader
344  unsigned d_attr_delay; // sample delay attribute for tag propagation
345 
346  //! constructor is private. Use gr::buffer::add_reader to create instances
347  buffer_reader(buffer_sptr buffer, unsigned int read_index, block_sptr link);
348 };
349 
350 //! returns # of buffer_readers currently allocated
352 
353 } /* namespace gr */
354 
355 #endif /* INCLUDED_GR_RUNTIME_BUFFER_H */
How we keep track of the readers of a gr::buffer.
Definition: buffer.h:247
const void * read_pointer()
return pointer to read buffer.
unsigned sample_delay() const
uint64_t nitems_read()
Definition: buffer.h:300
int items_available() const
Return number of items available for reading.
size_t get_sizeof_item()
Definition: buffer.h:304
void set_done(bool done)
Definition: buffer.h:295
void declare_sample_delay(unsigned delay)
bool done() const
Definition: buffer.h:296
buffer_sptr buffer() const
Return buffer this reader reads from.
Definition: buffer.h:275
void get_tags_in_range(std::vector< tag_t > &v, uint64_t abs_start, uint64_t abs_end, long id)
Given a [start,end), returns a vector all tags in the range.
void update_read_pointer(int nitems)
gr::thread::mutex * mutex()
Definition: buffer.h:298
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.
block_sptr link()
Return the block that reads via this reader.
Definition: buffer.h:310
void reset_nitem_counter()
Definition: buffer.h:302
int max_possible_items_available() const
Return maximum number of items that could ever be available for reading. This is used as a sanity che...
Definition: buffer.h:281
Single writer, multiple reader fifo.
Definition: buffer.h:47
size_t nreaders() const
Definition: buffer.h:90
unsigned d_max_reader_delay
Definition: buffer.h:160
friend GR_RUNTIME_API buffer_sptr make_buffer(int nitems, size_t sizeof_item, block_sptr link)
Allocate a buffer that holds at least nitems of size sizeof_item.
void remove_item_tag(const tag_t &tag, long id)
Removes an existing tag from the buffer.
const char * base() const
return the base address of the buffer
Definition: buffer.h:67
buffer_reader * reader(size_t index)
Definition: buffer.h:91
void prune_tags(uint64_t max_time)
Removes all tags before max_time from buffer.
bool done() const
Definition: buffer.h:83
void add_item_tag(const tag_t &tag)
Adds a new tag to the buffer.
gr::logger_ptr d_logger
Definition: buffer.h:49
gr::thread::mutex * mutex()
Definition: buffer.h:93
virtual ~buffer()
unsigned int d_bufsize
Definition: buffer.h:157
std::multimap< uint64_t, tag_t >::iterator get_tags_upper_bound(uint64_t x)
Definition: buffer.h:138
std::multimap< uint64_t, tag_t >::iterator get_tags_lower_bound(uint64_t x)
Definition: buffer.h:134
void reset_nitem_counter()
Definition: buffer.h:97
void set_done(bool done)
block_sptr link()
Return the block that writes to this buffer.
Definition: buffer.h:88
int space_available()
return number of items worth of space available for writing
size_t get_sizeof_item()
Definition: buffer.h:99
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 * write_pointer()
return pointer to write buffer.
void update_write_pointer(int nitems)
tell buffer that we wrote nitems into it
char * d_base
Definition: buffer.h:156
uint64_t nitems_written()
Definition: buffer.h:95
std::multimap< uint64_t, tag_t >::iterator get_tags_end()
Definition: buffer.h:133
std::multimap< uint64_t, tag_t >::iterator get_tags_begin()
Definition: buffer.h:129
gr::logger_ptr d_debug_logger
Definition: buffer.h:50
int bufsize() const
return size of this buffer in items
Definition: buffer.h:62
#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
GR_RUNTIME_API long buffer_reader_ncurrently_allocated()
returns # of buffer_readers currently allocated
GR_RUNTIME_API buffer_reader_sptr buffer_add_reader(buffer_sptr buf, int nzero_preload, block_sptr link=block_sptr(), int delay=0)
Create a new gr::buffer_reader and attach it to buffer buf.
log4cpp::Category * logger_ptr
GR_LOG macros.
Definition: logger.h:60
GR_RUNTIME_API long buffer_ncurrently_allocated()
returns # of buffers currently allocated
GR_RUNTIME_API buffer_sptr make_buffer(int nitems, size_t sizeof_item, block_sptr link=block_sptr())
Allocate a buffer that holds at least nitems of size sizeof_item.
Definition: tags.h:19
Definition: cc_common.h:35