Makefile.in: Remove special treatment of ortp_send/ortp_recv
[paraslash.git] / ringbuffer.c
1 /*
2 * Copyright (C) 2006 Andre Noll <maan@systemlinux.org>
3 *
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.
8 *
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.
13 *
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.
17 */
18
19 /** \file ringbuffer.c simple ringbuffer implementation */
20
21 #include "para.h"
22 #include "ringbuffer.h"
23 #include "string.h"
24
25 /**
26 * holds all information about one ring buffer
27 *
28 * It is intentionally not exported via ringbuffer.h. Think abstract.
29 */
30 struct ringbuffer
31 {
32 /**
33 *
34 *
35 * the size of this ring buffer
36 */
37 unsigned size;
38 /**
39 *
40 *
41 * the actual entries of the ringbuffer
42 */
43 void **entries;
44 /**
45 *
46 *
47 * the next entry will be added at this position
48 */
49 int head;
50 /**
51 *
52 * how many entries the ring buffer contains
53 */
54 unsigned filled;
55 };
56
57 /**
58 * initialize a new ringbuffer
59 *
60 * @param size the number of entries the ringbuffer holds
61 *
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'.
67 *
68 * Return value: A 'cookie' which identifies the ringbuffer just created and
69 * which must be passed to ringbuffer_add() and ringbuffer_get().
70 */
71 void *ringbuffer_new(unsigned size)
72 {
73 struct ringbuffer *rb = para_calloc(sizeof(struct ringbuffer));
74 rb->entries = para_calloc(size * sizeof(void *));
75 rb->size = size;
76 return rb;
77 };
78
79 /**
80 * add one entry to a ringbuffer
81 *
82 * @param cookie the ringbuffer identifier
83 * @param data the data to be inserted
84 *
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
87 * data.
88 *
89 * \return The old \a data pointer which is going to be disregarded, or
90 * NULL if the ringbuffer is not yet full.
91 */
92 void *ringbuffer_add(void *cookie, void *data)
93 {
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)
99 rb->filled++;
100 return ret;
101 }
102
103 /**
104 * get one entry from a ringbuffer
105 *
106 * @param cookie the ringbuffer identifier
107 * @param num the number of the entry
108 *
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.
112 */
113 void *ringbuffer_get(void *cookie, int num)
114 {
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];
119 }
120
121 /**
122 * get the number of entries in the ring buffer
123 *
124 * @param cookie the ringbuffer identifier
125 *
126 * This function always succeeds and never returns a number greater than the
127 * size of the ring buffer.
128 */
129 unsigned ringbuffer_filled(void *cookie)
130 {
131 struct ringbuffer *rb = cookie;
132 return rb->filled;
133 }