MINOR: ring: support creating a ring from a linear area

Instead of allocating two parts, one for the ring struct itself and
one for the storage area, ring_make_from_area() will arrange the two
inside the same memory area, with the storage starting immediately
after the struct. This will allow to store a complete ring state in
shared memory areas for example.
This commit is contained in:
Willy Tarreau 2022-08-12 07:50:43 +02:00
parent 8df098c2b1
commit 6df10d872b
2 changed files with 30 additions and 0 deletions

View File

@ -29,6 +29,7 @@
struct appctx;
struct ring *ring_new(size_t size);
struct ring *ring_make_from_area(void *area, size_t size);
void ring_init(struct ring *ring, void* area, size_t size);
struct ring *ring_resize(struct ring *ring, size_t size);
void ring_free(struct ring *ring);

View File

@ -75,6 +75,30 @@ struct ring *ring_new(size_t size)
return NULL;
}
/* Creates a unified ring + storage area at address <area> for <size> bytes.
* If <area> is null, then it's allocated of the requested size. The ring
* struct is part of the area so the usable area is slightly reduced. However
* the ring storage is immediately adjacent to the struct. ring_free() will
* ignore such rings, so the caller is responsible for releasing them.
*/
struct ring *ring_make_from_area(void *area, size_t size)
{
struct ring *ring = NULL;
if (size < sizeof(ring))
return NULL;
if (!area)
area = malloc(size);
if (!area)
return NULL;
ring = area;
area += sizeof(*ring);
ring_init(ring, area, size - sizeof(*ring));
return ring;
}
/* Resizes existing ring <ring> to <size> which must be larger, without losing
* its contents. The new size must be at least as large as the previous one or
* no change will be performed. The pointer to the ring is returned on success,
@ -113,6 +137,11 @@ void ring_free(struct ring *ring)
{
if (!ring)
return;
/* make sure it was not allocated by ring_make_from_area */
if (ring->buf.area == (void *)ring + sizeof(*ring))
return;
free(ring->buf.area);
free(ring);
}