2 * Copyright (C) 2006 Andre Noll <maan@systemlinux.org>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
19 /** \file ringbuffer.c simple ringbuffer implementation */
22 #include "ringbuffer.h"
26 * holds all information about one ring buffer
28 * It is intentionally not exported via ringbuffer.h. Think abstract.
35 * the size of this ring buffer
41 * the actual entries of the ringbuffer
47 * the next entry will be added at this position
52 * how many entries the ring buffer contains
58 * initialize a new ringbuffer
60 * @param size the number of entries the ringbuffer holds
62 * This function initializes a circular ring buffer which can hold up to \a
63 * size entries of arbitrary type. If performance is an issue, \a size should
64 * be a power of two to make the underlying modulo operations cheap. Arbitrary
65 * many ringbuffers may be initialized via this function. Each ringbuffer is
66 * identified by a 'cookie'.
68 * Return value: A 'cookie' which identifies the ringbuffer just created and
69 * which must be passed to ringbuffer_add() and ringbuffer_get().
71 void *ringbuffer_new(unsigned size)
73 struct ringbuffer *rb = para_calloc(sizeof(struct ringbuffer));
74 rb->entries = para_calloc(size * sizeof(void *));
80 * add one entry to a ringbuffer
82 * @param cookie the ringbuffer identifier
83 * @param data the data to be inserted
85 * insert \a data into the ringbuffer associated with \a cookie. As soon as
86 * the ringbuffer fills up, its oldest entry is disregarded and replaced by \a
89 * \return The old \a data pointer which is going to be disregarded, or
90 * NULL if the ringbuffer is not yet full.
92 void *ringbuffer_add(void *cookie, void *data)
94 struct ringbuffer *rb = cookie;
95 void *ret = rb->entries[rb->head];
96 rb->entries[rb->head] = data;
97 rb->head = (rb->head + 1) % rb->size;
98 if (rb->filled < rb->size)
104 * get one entry from a ringbuffer
106 * @param cookie the ringbuffer identifier
107 * @param num the number of the entry
109 * \return A pointer to data previously added, or NULL if entry number
110 * \a num is not available. \a num counts backwards from zero, i.e.
111 * ringbuffer_get_entry(0) gets the entry which was added most recently.
113 void *ringbuffer_get(void *cookie, int num)
115 struct ringbuffer *rb = cookie;
116 int pos = (rb->head + rb->size - 1 - num) % rb->size;
117 // fprintf(stderr, "pos = %d\n", pos);
118 return rb->entries[pos];
122 * get the number of entries in the ring buffer
124 * @param cookie the ringbuffer identifier
126 * This function always succeeds and never returns a number greater than the
127 * size of the ring buffer.
129 unsigned ringbuffer_filled(void *cookie)
131 struct ringbuffer *rb = cookie;