Skip to content

Commit 289e2a7

Browse files
committed
ringbuf2: Add *_areas functions.
Sometimes, it is useful to get all the memory areas readable or writable into a ringbuffer. This can be used e.g. to use pwrite() or to inspect all the ringbuffer entries without consuming them, or to obtain the whole contents at once, e.g. because one must hold onto a mutex to obtain them.
1 parent 4af2ff7 commit 289e2a7

File tree

3 files changed

+203
-9
lines changed

3 files changed

+203
-9
lines changed

src/csnip/ringbuf2.c

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,48 @@ size_t ringbuf2_get_write_idx(const ringbuf2* rb, size_t* ret_contig_write_max)
5151
return write_idx;
5252
}
5353

54+
int csnip_ringbuf2_get_write_areas(const ringbuf2* rb,
55+
size_t* ret_idx_0,
56+
size_t* ret_len_0,
57+
size_t* ret_idx_1,
58+
size_t* ret_len_1)
59+
{
60+
/* Buffer full? */
61+
if (rb->n_written - rb->n_read >= rb->cap)
62+
return 0;
63+
64+
/* Figure out geometry.
65+
*
66+
* If rdi <= wri, then there is free space wrap around,
67+
* i.e., there will be two contiguous write sections.
68+
*
69+
* Otherwise, there is a single section.
70+
*/
71+
const size_t wri = rb->n_written & (rb->cap - 1);
72+
const size_t rdi = rb->n_read & (rb->cap - 1);
73+
74+
if (ret_idx_0)
75+
*ret_idx_0 = wri;
76+
77+
if (rdi <= wri) {
78+
if (ret_len_0)
79+
*ret_len_0 = rb->cap - wri;
80+
if (rdi > 0) {
81+
if (ret_idx_1)
82+
*ret_idx_1 = 0;
83+
if (ret_len_1)
84+
*ret_len_1 = rdi;
85+
return 2;
86+
} else {
87+
return 1;
88+
}
89+
} else {
90+
if (ret_len_0)
91+
*ret_len_0 = rdi - wri;
92+
return 1;
93+
}
94+
}
95+
5496
bool ringbuf2_add_written(ringbuf2* rb, size_t n_written)
5597
{
5698
rb->n_written += n_written;
@@ -68,6 +110,48 @@ size_t ringbuf2_get_read_idx(const ringbuf2* rb, size_t* ret_contig_read_max)
68110
return read_idx;
69111
}
70112

113+
int csnip_ringbuf2_get_read_areas(const ringbuf2* rb,
114+
size_t* ret_idx_0,
115+
size_t* ret_len_0,
116+
size_t* ret_idx_1,
117+
size_t* ret_len_1)
118+
{
119+
/* Buffer empty? */
120+
if (rb->n_written - rb->n_read == 0)
121+
return 0;
122+
123+
/* Figure out geometry.
124+
*
125+
* If wri <= rdi, then there is read space wrap around,
126+
* i.e., there will be two contiguous read sections.
127+
*
128+
* Otherwise, there is a single section.
129+
*/
130+
const size_t wri = rb->n_written & (rb->cap - 1);
131+
const size_t rdi = rb->n_read & (rb->cap - 1);
132+
133+
if (ret_idx_0)
134+
*ret_idx_0 = rdi;
135+
136+
if (wri <= rdi) {
137+
if (ret_len_0)
138+
*ret_len_0 = rb->cap - rdi;
139+
if (wri > 0) {
140+
if (ret_idx_1)
141+
*ret_idx_1 = 0;
142+
if (ret_len_1)
143+
*ret_len_1 = wri;
144+
return 2;
145+
} else {
146+
return 1;
147+
}
148+
} else {
149+
if (ret_len_0)
150+
*ret_len_0 = wri - rdi;
151+
return 1;
152+
}
153+
}
154+
71155
bool ringbuf2_add_read(ringbuf2* rb, size_t n_read)
72156
{
73157
rb->n_read += n_read;

src/csnip/ringbuf2.h

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -57,23 +57,35 @@ size_t csnip_ringbuf2_free_size(const csnip_ringbuf2* rb);
5757

5858
size_t csnip_ringbuf2_get_write_idx(const csnip_ringbuf2* rb,
5959
size_t* ret_contig_write_max);
60+
int csnip_ringbuf2_get_write_areas(const csnip_ringbuf2* rb,
61+
size_t* ret_idx_0,
62+
size_t* ret_len_0,
63+
size_t* ret_idx_1,
64+
size_t* ret_len_1);
6065
bool csnip_ringbuf2_add_written(csnip_ringbuf2* rb, size_t n_written);
6166

6267
size_t csnip_ringbuf2_get_read_idx(const csnip_ringbuf2* rb,
6368
size_t* ret_contig_read_max);
69+
int csnip_ringbuf2_get_read_areas(const csnip_ringbuf2* rb,
70+
size_t* ret_idx_0,
71+
size_t* ret_len_0,
72+
size_t* ret_idx_1,
73+
size_t* ret_len_1);
6474
bool csnip_ringbuf2_add_read(csnip_ringbuf2* rb, size_t n_read);
6575

6676
#endif /* CSNIP_RINGBUF2_H */
6777

6878
#if defined(CSNIP_SHORT_NAMES) && !defined(CSNIP_RINGBUF2_HAVE_SHORT_NAMES)
69-
#define ringbuf2 csnip_ringbuf2
70-
#define ringbuf2_init csnip_ringbuf2_init
71-
#define ringbuf2_make csnip_ringbuf2_make
72-
#define ringbuf2_used_size csnip_ringbuf2_used_size
73-
#define ringbuf2_free_size csnip_ringbuf2_free_size
74-
#define ringbuf2_get_write_idx csnip_ringbuf2_get_write_idx
75-
#define ringbuf2_add_written csnip_ringbuf2_add_written
76-
#define ringbuf2_get_read_idx csnip_ringbuf2_get_read_idx
77-
#define ringbuf2_add_read csnip_ringbuf2_add_read
79+
#define ringbuf2 csnip_ringbuf2
80+
#define ringbuf2_init csnip_ringbuf2_init
81+
#define ringbuf2_make csnip_ringbuf2_make
82+
#define ringbuf2_used_size csnip_ringbuf2_used_size
83+
#define ringbuf2_free_size csnip_ringbuf2_free_size
84+
#define ringbuf2_get_write_idx csnip_ringbuf2_get_write_idx
85+
#define ringbuf2_get_write_areas csnip_ringbuf2_get_write_areas
86+
#define ringbuf2_add_written csnip_ringbuf2_add_written
87+
#define ringbuf2_get_read_idx csnip_ringbuf2_get_read_idx
88+
#define ringbuf2_get_read_areas csnip_ringbuf2_get_read_areas
89+
#define ringbuf2_add_read csnip_ringbuf2_add_read
7890
#define CSNIP_RINGBUF2_HAVE_SHORT_NAMES
7991
#endif /* CSNIP_SHORT_NAMES && !CSNIP_RINGBUF2_HAVE_SHORT_NAMES */

test/ringbuf2_test.c

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,55 @@ void straighttwisted_checks(void)
108108
CHECK(n_contig == rb.cap - widx);
109109
CHECK(ringbuf2_get_read_idx(&rb, &n_contig) == ridx);
110110
CHECK(n_contig == widx - ridx);
111+
{
112+
/* Test ringbuf2_get_read_areas() */
113+
size_t pos[2], len[2];
114+
int n = ringbuf2_get_read_areas(&rb,
115+
&pos[0], &len[0],
116+
&pos[1], &len[1]);
117+
CHECK(n == 0 || n == 1);
118+
size_t used_sz = ringbuf2_used_size(&rb);
119+
if (n == 0) {
120+
CHECK(used_sz == 0);
121+
} else {
122+
CHECK(len[0] > 0);
123+
CHECK(len[0] == used_sz);
124+
size_t cspc;
125+
size_t ri = ringbuf2_get_read_idx(&rb, &cspc);
126+
CHECK(cspc == len[0]);
127+
CHECK(ri == pos[0]);
128+
}
129+
}
130+
{
131+
/* Test ringbuf2_get_write_areas() */
132+
size_t pos[2], len[2];
133+
int n = ringbuf2_get_write_areas(&rb,
134+
&pos[0], &len[0],
135+
&pos[1], &len[1]);
136+
size_t free_sz = ringbuf2_free_size(&rb);
137+
size_t cspc;
138+
size_t wi = ringbuf2_get_write_idx(&rb, &cspc);
139+
switch (n) {
140+
case 0:
141+
CHECK(free_sz == 0);
142+
break;
143+
case 1:
144+
CHECK(len[0] > 0);
145+
CHECK(len[0] == free_sz);
146+
CHECK(cspc == len[0]);
147+
CHECK(wi == pos[0]);
148+
break;
149+
case 2:
150+
CHECK(len[0] > 0);
151+
CHECK(len[1] > 0);
152+
CHECK(len[0] + len[1] == free_sz);
153+
CHECK(cspc == len[0]);
154+
CHECK(cspc <= free_sz);
155+
CHECK(wi == pos[0]);
156+
CHECK(pos[1] == 0);
157+
break;
158+
};
159+
}
111160
if (ringbuf2_free_size(&rb) > 0) {
112161
CHECK(ringbuf2_add_written(&rb, 1));
113162
CHECK(ringbuf2_get_write_idx(&rb, NULL)
@@ -130,6 +179,55 @@ void straighttwisted_checks(void)
130179
CHECK(n_contig == ridx - widx);
131180
CHECK(ringbuf2_get_read_idx(&rb, &n_contig) == ridx);
132181
CHECK(n_contig == rb.cap - ridx);
182+
{
183+
/* Test ringbuf2_get_read_areas() */
184+
size_t pos[2], len[2];
185+
int n = ringbuf2_get_read_areas(&rb,
186+
&pos[0], &len[0],
187+
&pos[1], &len[1]);
188+
size_t used_sz = ringbuf2_used_size(&rb);
189+
size_t cspc;
190+
size_t ri = ringbuf2_get_read_idx(&rb, &cspc);
191+
switch (n) {
192+
case 0:
193+
CHECK(used_sz == 0);
194+
break;
195+
case 1:
196+
CHECK(len[0] > 0);
197+
CHECK(len[0] == used_sz);
198+
CHECK(cspc == len[0]);
199+
CHECK(ri == pos[0]);
200+
break;
201+
case 2:
202+
CHECK(len[0] > 0);
203+
CHECK(len[1] > 0);
204+
CHECK(len[0] + len[1] == used_sz);
205+
CHECK(cspc == len[0]);
206+
CHECK(cspc <= used_sz);
207+
CHECK(ri == pos[0]);
208+
CHECK(pos[1] == 0);
209+
break;
210+
};
211+
}
212+
{
213+
/* Test ringbuf2_get_write_areas() */
214+
size_t pos[2], len[2];
215+
int n = ringbuf2_get_write_areas(&rb,
216+
&pos[0], &len[0],
217+
&pos[1], &len[1]);
218+
CHECK(n == 0 || n == 1);
219+
size_t free_sz = ringbuf2_free_size(&rb);
220+
if (n == 0) {
221+
CHECK(free_sz == 0);
222+
} else {
223+
CHECK(len[0] > 0);
224+
CHECK(len[0] == free_sz);
225+
size_t cspc;
226+
size_t wi = ringbuf2_get_write_idx(&rb, &cspc);
227+
CHECK(cspc == len[0]);
228+
CHECK(wi == pos[0]);
229+
}
230+
}
133231
if (ringbuf2_free_size(&rb) > 0) {
134232
CHECK(ringbuf2_add_written(&rb, 1));
135233
CHECK(ringbuf2_get_write_idx(&rb, NULL)

0 commit comments

Comments
 (0)