1 /* FluidSynth - A Software Synthesizer
3 * Copyright (C) 2003 Peter Hanappe and others.
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public License
7 * as published by the Free Software Foundation; either version 2 of
8 * the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details.
15 * You should have received a copy of the GNU Library General Public
16 * License along with this library; if not, write to the Free
17 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21 #ifndef _FLUID_RINGBUFFER_H
22 #define _FLUID_RINGBUFFER_H
24 #include "fluid_sys.h"
27 * Lockless event queue instance.
29 struct _fluid_ringbuffer_t
31 char *array; /**< Queue array of arbitrary size elements */
32 int totalcount; /**< Total count of elements in array */
33 int count; /**< Current count of elements */
34 int in; /**< Index in queue to store next pushed element */
35 int out; /**< Index in queue of next popped element */
36 int elementsize; /**< Size of each element */
40 typedef struct _fluid_ringbuffer_t fluid_ringbuffer_t;
43 fluid_ringbuffer_t *new_fluid_ringbuffer (int count, int elementsize);
44 void delete_fluid_ringbuffer (fluid_ringbuffer_t *queue);
47 * Get pointer to next input array element in queue.
48 * @param queue Lockless queue instance
49 * @param count Normally zero, or more if you need to push several items at once
50 * @return Pointer to array element in queue to store data to or NULL if queue is full
52 * This function along with fluid_ringbuffer_next_inptr() form a queue "push"
53 * operation and is split into 2 functions to avoid an element copy. Note that
54 * the returned array element pointer may contain the data of a previous element
55 * if the queue has wrapped around. This can be used to reclaim pointers to
56 * allocated memory, etc.
58 static FLUID_INLINE void*
59 fluid_ringbuffer_get_inptr (fluid_ringbuffer_t *queue, int offset)
61 return fluid_atomic_int_get (&queue->count) + offset >= queue->totalcount ? NULL
62 : queue->array + queue->elementsize * ((queue->in + offset) % queue->totalcount);
66 * Advance the input queue index to complete a "push" operation.
67 * @param queue Lockless queue instance
68 * @param count Normally one, or more if you need to push several items at once
70 * This function along with fluid_ringbuffer_get_inptr() form a queue "push"
71 * operation and is split into 2 functions to avoid element copy.
73 static FLUID_INLINE void
74 fluid_ringbuffer_next_inptr (fluid_ringbuffer_t *queue, int count)
76 fluid_atomic_int_add (&queue->count, count);
79 if (queue->in >= queue->totalcount)
80 queue->in -= queue->totalcount;
84 * Get amount of items currently in queue
85 * @param queue Lockless queue instance
86 * @return amount of items currently in queue
88 static FLUID_INLINE int
89 fluid_ringbuffer_get_count (fluid_ringbuffer_t *queue)
91 return fluid_atomic_int_get (&queue->count);
96 * Get pointer to next output array element in queue.
97 * @param queue Lockless queue instance
98 * @return Pointer to array element data in the queue or NULL if empty, can only
99 * be used up until fluid_ringbuffer_next_outptr() is called.
101 * This function along with fluid_ringbuffer_next_outptr() form a queue "pop"
102 * operation and is split into 2 functions to avoid an element copy.
104 static FLUID_INLINE void*
105 fluid_ringbuffer_get_outptr (fluid_ringbuffer_t *queue)
107 return fluid_ringbuffer_get_count(queue) == 0 ? NULL
108 : queue->array + queue->elementsize * queue->out;
113 * Advance the output queue index to complete a "pop" operation.
114 * @param queue Lockless queue instance
116 * This function along with fluid_ringbuffer_get_outptr() form a queue "pop"
117 * operation and is split into 2 functions to avoid an element copy.
119 static FLUID_INLINE void
120 fluid_ringbuffer_next_outptr (fluid_ringbuffer_t *queue)
122 fluid_atomic_int_add (&queue->count, -1);
124 if (++queue->out == queue->totalcount)
128 #endif /* _FLUID_ringbuffer_H */