Loading...
Searching...
No Matches
buffer.h
Go to the documentation of this file.
/* -*- c++ -*- */
/*
* Copyright 2004,2009-2011,2013 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
* SPDX-License-Identifier: GPL-3.0-or-later
*
*/
#ifndef INCLUDED_GR_RUNTIME_BUFFER_H
#define INCLUDED_GR_RUNTIME_BUFFER_H
#include <gnuradio/api.h>
#include <gnuradio/custom_lock.h>
#include <gnuradio/logger.h>
#include <gnuradio/runtime_types.h>
#include <gnuradio/tags.h>
#include <gnuradio/thread/thread.h>
#include <gnuradio/transfer_type.h>
#include <functional>
#include <iostream>
#include <map>
#include <memory>
namespace gr {
class vmcircbuf;
class buffer_reader;
class buffer_reader_sm;
enum class buffer_mapping_type { double_mapped, single_mapped };
typedef std::function<void*(void*, const void*, std::size_t)> mem_func_t;
/*!
* \brief Allocate a buffer that holds at least \p nitems of size \p sizeof_item.
*
* The total size of the buffer will be rounded up to a system
* dependent boundary. This is typically the system page size, but
* under MS windows is 64KB.
*
* \param nitems is the minimum number of items the buffer will hold.
* \param sizeof_item is the size of an item in bytes.
* \param downstream_lcm_nitems is the least common multiple of the items to
* read by downstream block(s)
* \param downstream_max_out_mult is the maximum output multiple of all
* downstream blocks
* \param link is the block that writes to this buffer.
* \param buf_owner is the block that owns the buffer which may or may not
* be the same as the block that writes to this buffer
*/
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());
/*!
* \brief Single writer, multiple reader fifo.
* \ingroup internal
*/
class GR_RUNTIME_API buffer : public custom_lock_if
{
public:
gr::logger_ptr d_logger;
gr::logger_ptr d_debug_logger;
~buffer() override;
/*!
* \brief return the buffer's mapping type
*/
buffer_mapping_type get_mapping_type() { return d_buf_map_type; }
/*!
* \brief return number of items worth of space available for writing
*/
virtual int space_available() = 0;
/*!
* \brief return size of this buffer in items
*/
unsigned int bufsize() const { return d_bufsize; }
/*!
* \brief return the base address of the buffer
*/
const char* base() const { return static_cast<const char*>(d_base); }
/*!
* \brief return pointer to write buffer.
*
* The return value points at space that can hold at least
* space_available() items.
*/
virtual void* write_pointer();
/*!
* \brief return pointer to read buffer.
*
* The return value points to at least items_available() items.
*/
virtual const void* _read_pointer(unsigned int read_index);
/*!
* \brief tell buffer that we wrote \p nitems into it
*/
void update_write_pointer(int nitems);
void set_done(bool done);
bool done() const { return d_done; }
/*!
* \brief Return the block that writes to this buffer.
*/
block_sptr link() { return block_sptr(d_link); }
size_t nreaders() const { return d_readers.size(); }
buffer_reader* reader(size_t index) { return d_readers[index]; }
gr::thread::mutex* mutex() { return &d_mutex; }
uint64_t nitems_written() { return d_abs_write_offset; }
void reset_nitem_counter()
{
d_write_index = 0;
d_abs_write_offset = 0;
}
size_t get_sizeof_item() { return d_sizeof_item; }
uint64_t get_downstream_lcm_nitems() { return d_downstream_lcm_nitems; }
uint32_t get_max_reader_output_multiple() { return d_max_reader_output_multiple; }
virtual void update_reader_block_history(unsigned history, [[maybe_unused]] int delay)
{
d_max_reader_history = std::max(d_max_reader_history, history);
d_has_history = (d_max_reader_history > 1);
}
/*!
* \brief Adds a new tag to the buffer.
*
* \param tag the new tag
*/
void add_item_tag(const tag_t& tag);
/*!
* \brief Removes an existing tag from the buffer.
*
* If no such tag is found, does nothing.
* Note: Doesn't actually physically delete the tag, but
* marks it as deleted. For the user, this has the same effect:
* Any subsequent calls to get_tags_in_range() will not return
* the tag.
*
* \param tag the tag that needs to be removed
* \param id the unique ID of the block calling this function
*/
void remove_item_tag(const tag_t& tag, long id);
/*!
* \brief Removes all tags before \p max_time from buffer
*
* \param max_time the time (item number) to trim up until.
*/
void prune_tags(uint64_t max_time);
std::multimap<uint64_t, tag_t>::iterator get_tags_begin()
{
return d_item_tags.begin();
}
std::multimap<uint64_t, tag_t>::iterator get_tags_end() { return d_item_tags.end(); }
std::multimap<uint64_t, tag_t>::iterator get_tags_lower_bound(uint64_t x)
{
return d_item_tags.lower_bound(x);
}
std::multimap<uint64_t, tag_t>::iterator get_tags_upper_bound(uint64_t x)
{
return d_item_tags.upper_bound(x);
}
/*!
* \brief Function to be executed after this object's owner completes the
* call to general_work()
*/
virtual void post_work(int nitems) = 0;
/*!
* \brief Returns true when the current thread is ready to call the callback,
* false otherwise. Note if input_blocked_callback is overridden then this
* function should also be overridden.
*/
virtual bool input_blkd_cb_ready([[maybe_unused]] int items_required,
[[maybe_unused]] unsigned read_index)
{
return false;
}
/*!
* \brief Callback function that the scheduler will call when it determines
* that the input is blocked. Override this function if needed.
*/
virtual bool input_blocked_callback([[maybe_unused]] int items_required,
[[maybe_unused]] int items_avail,
[[maybe_unused]] unsigned read_index)
{
return false;
}
/*!
* \brief Returns true if the current thread is ready to execute
* output_blocked_callback(), false otherwise. Note if the default
* output_blocked_callback is overridden this function should also be
* overridden.
*/
virtual bool output_blkd_cb_ready([[maybe_unused]] int output_multiple)
{
return false;
}
/*!
* \brief Callback function that the scheduler will call when it determines
* that the output is blocked. Override this function if needed.
*/
virtual bool output_blocked_callback([[maybe_unused]] int output_multiple,
[[maybe_unused]] bool force = false)
{
return false;
}
/*!
* \brief Increment the number of active pointers for this buffer.
*/
inline void increment_active()
{
gr::thread::scoped_lock lock(d_mutex);
d_cv.wait(lock, [this]() { return d_callback_flag == false; });
++d_active_pointer_counter;
}
/*!
* \brief Decrement the number of active pointers for this buffer and signal
* anyone waiting when the count reaches zero.
*/
inline void decrement_active()
{
gr::thread::scoped_lock lock(d_mutex);
if (--d_active_pointer_counter == 0)
d_cv.notify_all();
}
/*!
* \brief "on_lock" function from the custom_lock_if.
*/
void on_lock(gr::thread::scoped_lock& lock) override;
/*!
* \brief "on_unlock" function from the custom_lock_if.
*/
void on_unlock() override;
friend std::ostream& operator<<(std::ostream& os, const buffer& buf);
// -------------------------------------------------------------------------
/*!
* \brief Assign buffer's transfer_type
*/
void set_transfer_type(const transfer_type& type);
private:
friend class buffer_reader;
friend class buffer_reader_sm;
friend GR_RUNTIME_API buffer_sptr make_buffer(int nitems,
size_t sizeof_item,
uint64_t downstream_lcm_nitems,
block_sptr link);
friend GR_RUNTIME_API buffer_reader_sptr buffer_add_reader(buffer_sptr buf,
int nzero_preload,
block_sptr link,
int delay);
protected:
char* d_base; // base address of buffer inside d_vmcircbuf.
unsigned int d_bufsize; // in items
buffer_mapping_type d_buf_map_type;
// Keep track of maximum sample delay of any reader; Only prune tags past this.
unsigned d_max_reader_delay;
// Keep track of the maximum sample history requirements of all blocks that
// consume from this buffer
unsigned d_max_reader_history;
// Indicates if d_max_reader_history > 1
bool d_has_history;
size_t d_sizeof_item; // in bytes
std::vector<buffer_reader*> d_readers;
std::weak_ptr<block> d_link; // block that writes to this buffer
//
// The mutex protects d_write_index, d_abs_write_offset, d_done, d_item_tags
// and the d_read_index's and d_abs_read_offset's in the buffer readers.
// Also d_callback_flag and d_active_pointer_counter.
//
gr::thread::mutex d_mutex;
unsigned int d_write_index; // in items [0,d_bufsize)
uint64_t d_abs_write_offset; // num items written since the start
bool d_done;
std::multimap<uint64_t, tag_t> d_item_tags;
uint64_t d_last_min_items_read;
//
gr::thread::condition_variable d_cv;
bool d_callback_flag;
uint32_t d_active_pointer_counter;
uint64_t d_downstream_lcm_nitems;
uint64_t d_write_multiple;
uint32_t d_max_reader_output_multiple;
transfer_type d_transfer_type;
/*!
* \brief Increment read or write index for this buffer
*/
virtual unsigned index_add(unsigned a, unsigned b) = 0;
/*!
* \brief Decrement read or write index for this buffer
*/
virtual unsigned index_sub(unsigned a, unsigned b) = 0;
virtual bool allocate_buffer([[maybe_unused]] int nitems) { return false; };
/*!
* \brief constructor is private. Use gr_make_buffer to create instances.
*
* Allocate a buffer that holds at least \p nitems of size \p sizeof_item.
*
* \param buftype is an enum type that describes the buffer TODO: fix me
* \param nitems is the minimum number of items the buffer will hold.
* \param sizeof_item is the size of an item in bytes.
* \param downstream_lcm_nitems is the least common multiple of the items to
* read by downstream block(s)
* \param downstream_max_out_mult is the maximum output multiple of all
* downstream blocks
* \param link is the block that writes to this buffer.
*
* The total size of the buffer will be rounded up to a system
* dependent boundary. This is typically the system page size, but
* under MS windows is 64KB.
*/
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);
/*!
* \brief disassociate \p reader from this buffer
*/
void drop_reader(buffer_reader* reader);
};
//! returns # of buffers currently allocated
GR_RUNTIME_API long buffer_ncurrently_allocated();
} /* namespace gr */
#endif /* INCLUDED_GR_RUNTIME_BUFFER_H */
gr::buffer_reader_sm
Definition buffer_reader_sm.h:22
gr::buffer_reader
How we keep track of the readers of a gr::buffer.
Definition buffer_reader.h:49
gr::buffer
Single writer, multiple reader fifo.
Definition buffer.h:67
gr::buffer::d_active_pointer_counter
uint32_t d_active_pointer_counter
Definition buffer.h:326
gr::buffer::nreaders
size_t nreaders() const
Definition buffer.h:122
gr::buffer::d_max_reader_delay
unsigned d_max_reader_delay
Definition buffer.h:299
gr::buffer::get_tags_lower_bound
std::multimap< uint64_t, tag_t >::iterator get_tags_lower_bound(uint64_t x)
Definition buffer.h:180
gr::buffer::write_pointer
virtual void * write_pointer()
return pointer to write buffer.
gr::buffer::get_tags_end
std::multimap< uint64_t, tag_t >::iterator get_tags_end()
Definition buffer.h:179
gr::buffer::remove_item_tag
void remove_item_tag(const tag_t &tag, long id)
Removes an existing tag from the buffer.
gr::buffer::d_mutex
gr::thread::mutex d_mutex
Definition buffer.h:317
gr::buffer::d_link
std::weak_ptr< block > d_link
Definition buffer.h:310
gr::buffer::get_downstream_lcm_nitems
uint64_t get_downstream_lcm_nitems()
Definition buffer.h:137
gr::buffer::d_write_multiple
uint64_t d_write_multiple
Definition buffer.h:329
gr::buffer::_read_pointer
virtual const void * _read_pointer(unsigned int read_index)
return pointer to read buffer.
gr::buffer::get_tags_upper_bound
std::multimap< uint64_t, tag_t >::iterator get_tags_upper_bound(uint64_t x)
Definition buffer.h:184
gr::buffer::prune_tags
void prune_tags(uint64_t max_time)
Removes all tags before max_time from buffer.
gr::buffer::allocate_buffer
virtual bool allocate_buffer(int nitems)
Definition buffer.h:344
gr::buffer::done
bool done() const
Definition buffer.h:115
gr::buffer::decrement_active
void decrement_active()
Decrement the number of active pointers for this buffer and signal anyone waiting when the count reac...
Definition buffer.h:253
gr::buffer::increment_active
void increment_active()
Increment the number of active pointers for this buffer.
Definition buffer.h:241
gr::buffer::add_item_tag
void add_item_tag(const tag_t &tag)
Adds a new tag to the buffer.
gr::buffer::post_work
virtual void post_work(int nitems)=0
Function to be executed after this object's owner completes the call to general_work()
gr::buffer::d_logger
gr::logger_ptr d_logger
Definition buffer.h:69
gr::buffer::index_add
virtual unsigned index_add(unsigned a, unsigned b)=0
Increment read or write index for this buffer.
gr::buffer::output_blkd_cb_ready
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:223
gr::buffer::make_buffer
friend GR_RUNTIME_API buffer_sptr make_buffer(int nitems, size_t sizeof_item, uint64_t downstream_lcm_nitems, block_sptr link)
gr::buffer::buffer_add_reader
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.
gr::buffer::d_bufsize
unsigned int d_bufsize
Definition buffer.h:295
gr::buffer::input_blocked_callback
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:210
gr::buffer::output_blocked_callback
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:232
gr::buffer::d_max_reader_output_multiple
uint32_t d_max_reader_output_multiple
Definition buffer.h:330
gr::buffer::~buffer
~buffer() override
gr::buffer::reader
buffer_reader * reader(size_t index)
Definition buffer.h:123
gr::buffer::operator<<
friend std::ostream & operator<<(std::ostream &os, const buffer &buf)
gr::buffer::reset_nitem_counter
void reset_nitem_counter()
Definition buffer.h:129
gr::buffer::on_unlock
void on_unlock() override
"on_unlock" function from the custom_lock_if.
gr::buffer::d_abs_write_offset
uint64_t d_abs_write_offset
Definition buffer.h:319
gr::buffer::d_buf_map_type
buffer_mapping_type d_buf_map_type
Definition buffer.h:296
gr::buffer::get_max_reader_output_multiple
uint32_t get_max_reader_output_multiple()
Definition buffer.h:139
gr::buffer::d_has_history
bool d_has_history
Definition buffer.h:306
gr::buffer::space_available
virtual int space_available()=0
return number of items worth of space available for writing
gr::buffer::set_done
void set_done(bool done)
gr::buffer::drop_reader
void drop_reader(buffer_reader *reader)
disassociate reader from this buffer
gr::buffer::input_blkd_cb_ready
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:200
gr::buffer::link
block_sptr link()
Return the block that writes to this buffer.
Definition buffer.h:120
gr::buffer::get_mapping_type
buffer_mapping_type get_mapping_type()
return the buffer's mapping type
Definition buffer.h:77
gr::buffer::update_reader_block_history
virtual void update_reader_block_history(unsigned history, int delay)
Definition buffer.h:141
gr::buffer::set_transfer_type
void set_transfer_type(const transfer_type &type)
Assign buffer's transfer_type.
gr::buffer::get_sizeof_item
size_t get_sizeof_item()
Definition buffer.h:135
gr::buffer::base
const char * base() const
return the base address of the buffer
Definition buffer.h:92
gr::buffer::bufsize
unsigned int bufsize() const
return size of this buffer in items
Definition buffer.h:87
gr::buffer::d_downstream_lcm_nitems
uint64_t d_downstream_lcm_nitems
Definition buffer.h:328
gr::buffer::d_item_tags
std::multimap< uint64_t, tag_t > d_item_tags
Definition buffer.h:321
gr::buffer::d_readers
std::vector< buffer_reader * > d_readers
Definition buffer.h:309
gr::buffer::on_lock
void on_lock(gr::thread::scoped_lock &lock) override
"on_lock" function from the custom_lock_if.
gr::buffer::d_max_reader_history
unsigned d_max_reader_history
Definition buffer.h:303
gr::buffer::update_write_pointer
void update_write_pointer(int nitems)
tell buffer that we wrote nitems into it
gr::buffer::d_done
bool d_done
Definition buffer.h:320
gr::buffer::d_write_index
unsigned int d_write_index
Definition buffer.h:318
gr::buffer::get_tags_begin
std::multimap< uint64_t, tag_t >::iterator get_tags_begin()
Definition buffer.h:175
gr::buffer::d_base
char * d_base
Definition buffer.h:294
gr::buffer::index_sub
virtual unsigned index_sub(unsigned a, unsigned b)=0
Decrement read or write index for this buffer.
gr::buffer::mutex
gr::thread::mutex * mutex()
Definition buffer.h:125
gr::buffer::nitems_written
uint64_t nitems_written()
Definition buffer.h:127
gr::buffer::d_sizeof_item
size_t d_sizeof_item
Definition buffer.h:308
gr::buffer::buffer
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.
gr::buffer::d_transfer_type
transfer_type d_transfer_type
Definition buffer.h:332
gr::buffer::d_cv
gr::thread::condition_variable d_cv
Definition buffer.h:324
gr::buffer::d_debug_logger
gr::logger_ptr d_debug_logger
Definition buffer.h:70
gr::buffer::d_last_min_items_read
uint64_t d_last_min_items_read
Definition buffer.h:322
gr::buffer::d_callback_flag
bool d_callback_flag
Definition buffer.h:325
gr::custom_lock_if
Definition custom_lock.h:27
std::vector
STL class.
Definition vector_docstub.h:11
custom_lock.h
api.h
GR_RUNTIME_API
#define GR_RUNTIME_API
Definition gnuradio-runtime/include/gnuradio/api.h:18
logger.h
gr::thread::mutex
boost::mutex mutex
Definition thread.h:37
gr::thread::scoped_lock
boost::unique_lock< boost::mutex > scoped_lock
Definition thread.h:38
gr::thread::condition_variable
boost::condition_variable condition_variable
Definition thread.h:39
gr
GNU Radio logging wrapper.
Definition basic_block.h:29
gr::mem_func_t
std::function< void *(void *, const void *, std::size_t)> mem_func_t
Definition buffer.h:36
gr::logger_ptr
std::shared_ptr< logger > logger_ptr
Definition logger.h:250
gr::make_buffer
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.
gr::transfer_type
transfer_type
Definition transfer_type.h:19
gr::buffer_mapping_type
buffer_mapping_type
Definition buffer.h:34
gr::buffer_mapping_type::double_mapped
@ double_mapped
gr::buffer_mapping_type::single_mapped
@ single_mapped
gr::buffer_ncurrently_allocated
GR_RUNTIME_API long buffer_ncurrently_allocated()
returns # of buffers currently allocated
runtime_types.h
gr::buftype
Template used to create buffer types. Note that the factory_class parameter must contain a static fun...
Definition buffer_type.h:94
gr::tag_t
Definition tags.h:19
tags.h
thread.h
transfer_type.h