~ubuntu-branches/ubuntu/trusty/jack-audio-connection-kit/trusty

« back to all changes in this revision

Viewing changes to libjack/ringbuffer.c

  • Committer: Bazaar Package Importer
  • Author(s): Luca Falavigna
  • Date: 2008-12-06 11:05:15 UTC
  • mfrom: (4.1.3 sid)
  • Revision ID: james.westby@ubuntu.com-20081206110515-xa9v9pajr9jqvfvg
Tags: 0.115.6-1ubuntu1
* Merge from Debian unstable, remaining Ubuntu changes:
  - Redirect stderr in bash completion (Debian #504488).

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
  Copyright (C) 2000 Paul Davis
 
3
  Copyright (C) 2003 Rohan Drape
 
4
    
 
5
  This program is free software; you can redistribute it and/or modify
 
6
  it under the terms of the GNU Lesser General Public License as published by
 
7
  the Free Software Foundation; either version 2.1 of the License, or
 
8
  (at your option) any later version.
 
9
    
 
10
  This program is distributed in the hope that it will be useful,
 
11
  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
13
  GNU Lesser General Public License for more details.
 
14
    
 
15
  You should have received a copy of the GNU Lesser General Public License
 
16
  along with this program; if not, write to the Free Software 
 
17
  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 
18
    
 
19
  ISO/POSIX C version of Paul Davis's lock free ringbuffer C++ code.
 
20
  This is safe for the case of one read thread and one write thread.
 
21
*/
 
22
 
 
23
#include <config.h>
 
24
 
 
25
#include <stdlib.h>
 
26
#include <string.h>
 
27
#ifdef USE_MLOCK
 
28
#include <sys/mman.h>
 
29
#endif /* USE_MLOCK */
 
30
#include <jack/ringbuffer.h>
 
31
 
 
32
/* Create a new ringbuffer to hold at least `sz' bytes of data. The
 
33
   actual buffer size is rounded up to the next power of two.  */
 
34
 
 
35
jack_ringbuffer_t *
 
36
jack_ringbuffer_create (size_t sz)
 
37
{
 
38
  int power_of_two;
 
39
  jack_ringbuffer_t *rb;
 
40
 
 
41
  rb = malloc (sizeof (jack_ringbuffer_t));
 
42
 
 
43
  for (power_of_two = 1; 1 << power_of_two < sz; power_of_two++);
 
44
 
 
45
  rb->size = 1 << power_of_two;
 
46
  rb->size_mask = rb->size;
 
47
  rb->size_mask -= 1;
 
48
  rb->write_ptr = 0;
 
49
  rb->read_ptr = 0;
 
50
  rb->buf = malloc (rb->size);
 
51
  rb->mlocked = 0;
 
52
 
 
53
  return rb;
 
54
}
 
55
 
 
56
/* Free all data associated with the ringbuffer `rb'. */
 
57
 
 
58
void
 
59
jack_ringbuffer_free (jack_ringbuffer_t * rb)
 
60
{
 
61
#ifdef USE_MLOCK
 
62
  if (rb->mlocked) {
 
63
    munlock (rb->buf, rb->size);
 
64
  }
 
65
#endif /* USE_MLOCK */
 
66
  free (rb->buf);
 
67
  free (rb);
 
68
}
 
69
 
 
70
/* Lock the data block of `rb' using the system call 'mlock'.  */
 
71
 
 
72
int
 
73
jack_ringbuffer_mlock (jack_ringbuffer_t * rb)
 
74
{
 
75
#ifdef USE_MLOCK
 
76
  if (mlock (rb->buf, rb->size)) {
 
77
    return -1;
 
78
  }
 
79
#endif /* USE_MLOCK */
 
80
  rb->mlocked = 1;
 
81
  return 0;
 
82
}
 
83
 
 
84
/* Reset the read and write pointers to zero. This is not thread
 
85
   safe. */
 
86
 
 
87
void
 
88
jack_ringbuffer_reset (jack_ringbuffer_t * rb)
 
89
{
 
90
  rb->read_ptr = 0;
 
91
  rb->write_ptr = 0;
 
92
}
 
93
 
 
94
/* Return the number of bytes available for reading.  This is the
 
95
   number of bytes in front of the read pointer and behind the write
 
96
   pointer.  */
 
97
 
 
98
size_t
 
99
jack_ringbuffer_read_space (const jack_ringbuffer_t * rb)
 
100
{
 
101
  size_t w, r;
 
102
 
 
103
  w = rb->write_ptr;
 
104
  r = rb->read_ptr;
 
105
 
 
106
  if (w > r) {
 
107
    return w - r;
 
108
  } else {
 
109
    return (w - r + rb->size) & rb->size_mask;
 
110
  }
 
111
}
 
112
 
 
113
/* Return the number of bytes available for writing.  This is the
 
114
   number of bytes in front of the write pointer and behind the read
 
115
   pointer.  */
 
116
 
 
117
size_t
 
118
jack_ringbuffer_write_space (const jack_ringbuffer_t * rb)
 
119
{
 
120
  size_t w, r;
 
121
 
 
122
  w = rb->write_ptr;
 
123
  r = rb->read_ptr;
 
124
 
 
125
  if (w > r) {
 
126
    return ((r - w + rb->size) & rb->size_mask) - 1;
 
127
  } else if (w < r) {
 
128
    return (r - w) - 1;
 
129
  } else {
 
130
    return rb->size - 1;
 
131
  }
 
132
}
 
133
 
 
134
/* The copying data reader.  Copy at most `cnt' bytes from `rb' to
 
135
   `dest'.  Returns the actual number of bytes copied. */
 
136
 
 
137
size_t
 
138
jack_ringbuffer_read (jack_ringbuffer_t * rb, char *dest, size_t cnt)
 
139
{
 
140
  size_t free_cnt;
 
141
  size_t cnt2;
 
142
  size_t to_read;
 
143
  size_t n1, n2;
 
144
 
 
145
  if ((free_cnt = jack_ringbuffer_read_space (rb)) == 0) {
 
146
    return 0;
 
147
  }
 
148
 
 
149
  to_read = cnt > free_cnt ? free_cnt : cnt;
 
150
 
 
151
  cnt2 = rb->read_ptr + to_read;
 
152
 
 
153
  if (cnt2 > rb->size) {
 
154
    n1 = rb->size - rb->read_ptr;
 
155
    n2 = cnt2 & rb->size_mask;
 
156
  } else {
 
157
    n1 = to_read;
 
158
    n2 = 0;
 
159
  }
 
160
 
 
161
  memcpy (dest, &(rb->buf[rb->read_ptr]), n1);
 
162
  rb->read_ptr = (rb->read_ptr + n1) & rb->size_mask;
 
163
 
 
164
  if (n2) {
 
165
    memcpy (dest + n1, &(rb->buf[rb->read_ptr]), n2);
 
166
    rb->read_ptr = (rb->read_ptr + n2) & rb->size_mask;
 
167
  }
 
168
 
 
169
  return to_read;
 
170
}
 
171
 
 
172
/* The copying data reader w/o read pointer advance.  Copy at most 
 
173
   `cnt' bytes from `rb' to `dest'.  Returns the actual number of bytes 
 
174
copied. */
 
175
 
 
176
size_t
 
177
jack_ringbuffer_peek (jack_ringbuffer_t * rb, char *dest, size_t cnt)
 
178
{
 
179
  size_t free_cnt;
 
180
  size_t cnt2;
 
181
  size_t to_read;
 
182
  size_t n1, n2;
 
183
  size_t tmp_read_ptr;
 
184
 
 
185
  tmp_read_ptr = rb->read_ptr;
 
186
 
 
187
  if ((free_cnt = jack_ringbuffer_read_space (rb)) == 0) {
 
188
    return 0;
 
189
  }
 
190
 
 
191
  to_read = cnt > free_cnt ? free_cnt : cnt;
 
192
 
 
193
  cnt2 = tmp_read_ptr + to_read;
 
194
 
 
195
  if (cnt2 > rb->size) {
 
196
    n1 = rb->size - tmp_read_ptr;
 
197
    n2 = cnt2 & rb->size_mask;
 
198
  } else {
 
199
    n1 = to_read;
 
200
    n2 = 0;
 
201
  }
 
202
 
 
203
  memcpy (dest, &(rb->buf[tmp_read_ptr]), n1);
 
204
  tmp_read_ptr = (tmp_read_ptr + n1) & rb->size_mask;
 
205
 
 
206
  if (n2) {
 
207
    memcpy (dest + n1, &(rb->buf[tmp_read_ptr]), n2);
 
208
  }
 
209
 
 
210
  return to_read;
 
211
}
 
212
 
 
213
 
 
214
/* The copying data writer.  Copy at most `cnt' bytes to `rb' from
 
215
   `src'.  Returns the actual number of bytes copied. */
 
216
 
 
217
size_t
 
218
jack_ringbuffer_write (jack_ringbuffer_t * rb, const char *src, size_t cnt)
 
219
{
 
220
  size_t free_cnt;
 
221
  size_t cnt2;
 
222
  size_t to_write;
 
223
  size_t n1, n2;
 
224
 
 
225
  if ((free_cnt = jack_ringbuffer_write_space (rb)) == 0) {
 
226
    return 0;
 
227
  }
 
228
 
 
229
  to_write = cnt > free_cnt ? free_cnt : cnt;
 
230
 
 
231
  cnt2 = rb->write_ptr + to_write;
 
232
 
 
233
  if (cnt2 > rb->size) {
 
234
    n1 = rb->size - rb->write_ptr;
 
235
    n2 = cnt2 & rb->size_mask;
 
236
  } else {
 
237
    n1 = to_write;
 
238
    n2 = 0;
 
239
  }
 
240
 
 
241
  memcpy (&(rb->buf[rb->write_ptr]), src, n1);
 
242
  rb->write_ptr = (rb->write_ptr + n1) & rb->size_mask;
 
243
 
 
244
  if (n2) {
 
245
    memcpy (&(rb->buf[rb->write_ptr]), src + n1, n2);
 
246
    rb->write_ptr = (rb->write_ptr + n2) & rb->size_mask;
 
247
  }
 
248
 
 
249
  return to_write;
 
250
}
 
251
 
 
252
/* Advance the read pointer `cnt' places. */
 
253
 
 
254
void
 
255
jack_ringbuffer_read_advance (jack_ringbuffer_t * rb, size_t cnt)
 
256
{
 
257
  size_t tmp = (rb->read_ptr + cnt) & rb->size_mask;
 
258
  rb->read_ptr = tmp;
 
259
}
 
260
 
 
261
/* Advance the write pointer `cnt' places. */
 
262
 
 
263
void
 
264
jack_ringbuffer_write_advance (jack_ringbuffer_t * rb, size_t cnt)
 
265
{
 
266
  size_t tmp = (rb->write_ptr + cnt) & rb->size_mask;
 
267
  rb->write_ptr = tmp;
 
268
}
 
269
 
 
270
/* The non-copying data reader.  `vec' is an array of two places.  Set
 
271
   the values at `vec' to hold the current readable data at `rb'.  If
 
272
   the readable data is in one segment the second segment has zero
 
273
   length.  */
 
274
 
 
275
void
 
276
jack_ringbuffer_get_read_vector (const jack_ringbuffer_t * rb,
 
277
                                 jack_ringbuffer_data_t * vec)
 
278
{
 
279
  size_t free_cnt;
 
280
  size_t cnt2;
 
281
  size_t w, r;
 
282
 
 
283
  w = rb->write_ptr;
 
284
  r = rb->read_ptr;
 
285
 
 
286
  if (w > r) {
 
287
    free_cnt = w - r;
 
288
  } else {
 
289
    free_cnt = (w - r + rb->size) & rb->size_mask;
 
290
  }
 
291
 
 
292
  cnt2 = r + free_cnt;
 
293
 
 
294
  if (cnt2 > rb->size) {
 
295
 
 
296
    /* Two part vector: the rest of the buffer after the current write
 
297
       ptr, plus some from the start of the buffer. */
 
298
 
 
299
    vec[0].buf = &(rb->buf[r]);
 
300
    vec[0].len = rb->size - r;
 
301
    vec[1].buf = rb->buf;
 
302
    vec[1].len = cnt2 & rb->size_mask;
 
303
 
 
304
  } else {
 
305
 
 
306
    /* Single part vector: just the rest of the buffer */
 
307
 
 
308
    vec[0].buf = &(rb->buf[r]);
 
309
    vec[0].len = free_cnt;
 
310
    vec[1].len = 0;
 
311
  }
 
312
}
 
313
 
 
314
/* The non-copying data writer.  `vec' is an array of two places.  Set
 
315
   the values at `vec' to hold the current writeable data at `rb'.  If
 
316
   the writeable data is in one segment the second segment has zero
 
317
   length.  */
 
318
 
 
319
void
 
320
jack_ringbuffer_get_write_vector (const jack_ringbuffer_t * rb,
 
321
                                  jack_ringbuffer_data_t * vec)
 
322
{
 
323
  size_t free_cnt;
 
324
  size_t cnt2;
 
325
  size_t w, r;
 
326
 
 
327
  w = rb->write_ptr;
 
328
  r = rb->read_ptr;
 
329
 
 
330
  if (w > r) {
 
331
    free_cnt = ((r - w + rb->size) & rb->size_mask) - 1;
 
332
  } else if (w < r) {
 
333
    free_cnt = (r - w) - 1;
 
334
  } else {
 
335
    free_cnt = rb->size - 1;
 
336
  }
 
337
 
 
338
  cnt2 = w + free_cnt;
 
339
 
 
340
  if (cnt2 > rb->size) {
 
341
 
 
342
    /* Two part vector: the rest of the buffer after the current write
 
343
       ptr, plus some from the start of the buffer. */
 
344
 
 
345
    vec[0].buf = &(rb->buf[w]);
 
346
    vec[0].len = rb->size - w;
 
347
    vec[1].buf = rb->buf;
 
348
    vec[1].len = cnt2 & rb->size_mask;
 
349
  } else {
 
350
    vec[0].buf = &(rb->buf[w]);
 
351
    vec[0].len = free_cnt;
 
352
    vec[1].len = 0;
 
353
  }
 
354
}