GNU Radio Manual and C++ API Reference 3.9.4.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 * 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>
17#include <gnuradio/tags.h>
19#include <boost/weak_ptr.hpp>
20#include <map>
21#include <memory>
22
23namespace gr {
24
25class 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 */
38GR_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{
48public:
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 */
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
145private:
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
155protected:
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
162private:
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 */
231GR_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{
248public:
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
333private:
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
unsigned sample_delay() const
uint64_t nitems_read()
Definition: buffer.h:300
int items_available() const
Return number of items available for reading.
const void * read_pointer()
return pointer to read buffer.
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
std::multimap< uint64_t, tag_t >::iterator get_tags_lower_bound(uint64_t x)
Definition: buffer.h:134
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.
std::multimap< uint64_t, tag_t >::iterator get_tags_end()
Definition: buffer.h:133
void remove_item_tag(const tag_t &tag, long id)
Removes an existing tag from the buffer.
void * write_pointer()
return pointer to write buffer.
std::multimap< uint64_t, tag_t >::iterator get_tags_upper_bound(uint64_t x)
Definition: buffer.h:138
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
virtual ~buffer()
unsigned int d_bufsize
Definition: buffer.h:157
buffer_reader * reader(size_t index)
Definition: buffer.h:91
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
const char * base() const
return the base address of the buffer
Definition: buffer.h:67
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 update_write_pointer(int nitems)
tell buffer that we wrote nitems into it
std::multimap< uint64_t, tag_t >::iterator get_tags_begin()
Definition: buffer.h:129
char * d_base
Definition: buffer.h:156
gr::thread::mutex * mutex()
Definition: buffer.h:93
uint64_t nitems_written()
Definition: buffer.h:95
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