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