1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
|
/* -*- c++ -*- */
/*
* Copyright 2020 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
* SPDX-License-Identifier: GPL-3.0-or-later
*
*/
#ifndef INCLUDED_GR_RUNTIME_BUFFER_SINGLE_MAPPED_H
#define INCLUDED_GR_RUNTIME_BUFFER_SINGLE_MAPPED_H
#include <cstddef>
#include <functional>
#include <gnuradio/api.h>
#include <gnuradio/buffer.h>
#include <gnuradio/buffer_reader.h>
#include <gnuradio/logger.h>
#include <gnuradio/runtime_types.h>
namespace gr {
/*!
* \brief A single mapped buffer where wrapping conditions are handled explicitly
* via input/output_blocked_callback functions called from block_executor.
* \ingroup internal
*/
class GR_RUNTIME_API buffer_single_mapped : public buffer
{
public:
gr::logger_ptr d_logger;
gr::logger_ptr d_debug_logger;
~buffer_single_mapped() override;
/*!
* \brief Return the block that owns this buffer.
*/
block_sptr buf_owner() { return d_buf_owner; }
/*!
* \brief return number of items worth of space available for writing
*/
int space_available() override;
void update_reader_block_history(unsigned history, int delay) override;
/*!
* \brief Return true if thread is ready to call input_blocked_callback,
* false otherwise
*/
bool input_blkd_cb_ready(int items_required, unsigned read_index) override;
/*!
* \brief Callback function that the scheduler will call when it determines
* that the input is blocked. Override this function if needed.
*/
bool input_blocked_callback(int items_required,
int items_avail,
unsigned read_index) override = 0;
/*!
* \brief Return true if thread is ready to call the callback, false otherwise
*/
bool output_blkd_cb_ready(int output_multiple) override;
/*!
* \brief Callback function that the scheduler will call when it determines
* that the output is blocked
*/
bool output_blocked_callback(int output_multiple, bool force) override = 0;
protected:
/*!
* \brief Make reasonable attempt to adjust nitems based on read/write
* granularity then delegate actual allocation to do_allocate_buffer().
* @return true iff successful.
*/
bool allocate_buffer(int nitems) override;
/*!
* \brief Do actual buffer allocation. This is intended (required) to be
* handled by the derived class.
*/
virtual bool do_allocate_buffer(size_t final_nitems, size_t sizeof_item) = 0;
unsigned index_add(unsigned a, unsigned b) override
{
unsigned s = a + b;
if (s >= d_bufsize)
s -= d_bufsize;
assert(s < d_bufsize);
return s;
}
unsigned index_sub(unsigned a, unsigned b) override
{
// NOTE: a is writer ptr and b is read ptr
int s = a - b;
if (s < 0)
s = d_bufsize - b;
assert((unsigned)s < d_bufsize);
return s;
}
friend class buffer_reader;
friend GR_RUNTIME_API buffer_sptr make_buffer(int nitems,
size_t sizeof_item,
uint64_t downstream_lcm_nitems,
block_sptr link,
block_sptr buf_owner);
block_sptr d_buf_owner; // block that "owns" this buffer
std::unique_ptr<char> d_buffer;
/*!
* \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 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 blocks
* \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 if the block that owns the buffer which may or may not
* be the same as 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_single_mapped(int nitems,
size_t sizeof_item,
uint64_t downstream_lcm_nitems,
uint32_t downstream_max_out_mult,
block_sptr link,
block_sptr buf_owner);
/*!
* \brief Abstracted logic for the input blocked callback function.
*
* This function contains the logic for the input blocked callback however
* the data adjustment portion of the callback has been abstracted to allow
* the caller to pass in the desired buffer and corresponding buffer
* manipulation functions (memcpy and memmove).
*
* The input blocked callback is called when a reader needs to read more
* data than is available in a buffer and the available data is located at
* the end of the buffer. The input blocked callback will attempt to move
* any data located at the beginning of the buffer "down", and will then
* attempt to copy from the end of the buffer back to the beginning of the
* buffer. This process explicitly handles wrapping for a single mapped
* buffer and will realign the data at the beginning of the buffer such
* that the reader is able to read the available data and becomes unblocked.
*
* \param items_required is the number of items required by the reader
* \param items_avail is the number of items available
* \param read_index is the current read index of the buffer reader caller
* \param buffer_ptr is the pointer to the desired buffer
* \param memcpy_func is a pointer to a memcpy function appropriate for the
* the passed in buffer
* \param memmove_func is a pointer to a memmove function appropriate for
* the passed in buffer
*/
virtual bool input_blocked_callback_logic(int items_required,
int items_avail,
unsigned read_index,
char* buffer_ptr,
mem_func_t const& memcpy_func,
mem_func_t const& memmove_func);
/*!
* \brief Abstracted logic for the output blocked callback function.
*
* This function contains the logic for the output blocked callback however
* the data adjustment portion of the callback has been abstracted to allow
* the caller to pass in the desired buffer and corresponding buffer
* manipulation functions (memcpy and memmove).
*
* The output blocked callback is called when a block needs to write data
* to the end of a single mapped buffer but not enough free space exists to
* write the data before the end of the buffer is reached. The output blocked
* callback will attempt to copy data located towards the end of a single
* mapped buffer back to the beginning of the buffer. This process explicitly
* handles wrapping for a single mapped buffer and will realign data located
* at the end of a buffer back to the beginning of the buffer such that the
* writing block can write its output into the buffer after the existing data.
*
* \param output_multiple
* \param force run the callback disregarding the internal checks
* \param buffer_ptr is the pointer to the desired buffer
* \param memmove_func is a pointer to a memmove function appropriate for
* the passed in buffer
*/
virtual bool output_blocked_callback_logic(int output_multiple,
bool force,
char* buffer_ptr,
mem_func_t const& memmove_func);
};
} /* namespace gr */
#endif /* INCLUDED_GR_RUNTIME_BUFFER_SINGLE_MAPPED_H */
|