new header file for superclock stuff
[ardour.git] / libs / fluidsynth / src / fluid_ringbuffer.h
1 /* FluidSynth - A Software Synthesizer
2  *
3  * Copyright (C) 2003  Peter Hanappe and others.
4  *
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.
9  *
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.
14  *
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
18  * 02110-1301, USA
19  */
20
21 #ifndef _FLUID_RINGBUFFER_H
22 #define _FLUID_RINGBUFFER_H
23
24 #include "fluid_sys.h"
25
26 /**
27  * Lockless event queue instance.
28  */
29 struct _fluid_ringbuffer_t
30 {
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 */
37   void* userdata;     
38 };
39
40 typedef struct _fluid_ringbuffer_t fluid_ringbuffer_t;
41
42
43 fluid_ringbuffer_t *new_fluid_ringbuffer (int count, int elementsize);
44 void delete_fluid_ringbuffer (fluid_ringbuffer_t *queue);
45
46 /**
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
51  *
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.
57  */
58 static FLUID_INLINE void*
59 fluid_ringbuffer_get_inptr (fluid_ringbuffer_t *queue, int offset)
60 {
61   return fluid_atomic_int_get (&queue->count) + offset >= queue->totalcount ? NULL
62     : queue->array + queue->elementsize * ((queue->in + offset) % queue->totalcount);
63 }
64
65 /**
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
69  *
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.
72  */
73 static FLUID_INLINE void
74 fluid_ringbuffer_next_inptr (fluid_ringbuffer_t *queue, int count)
75 {
76   fluid_atomic_int_add (&queue->count, count);
77
78   queue->in += count;
79   if (queue->in >= queue->totalcount)
80     queue->in -= queue->totalcount;
81 }
82
83 /**
84  * Get amount of items currently in queue
85  * @param queue Lockless queue instance
86  * @return amount of items currently in queue
87  */
88 static FLUID_INLINE int
89 fluid_ringbuffer_get_count (fluid_ringbuffer_t *queue)
90 {
91   return fluid_atomic_int_get (&queue->count);
92 }
93
94
95 /**
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.
100  *
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.
103  */
104 static FLUID_INLINE void*
105 fluid_ringbuffer_get_outptr (fluid_ringbuffer_t *queue)
106 {
107   return fluid_ringbuffer_get_count(queue) == 0 ? NULL
108     : queue->array + queue->elementsize * queue->out;
109 }
110
111
112 /**
113  * Advance the output queue index to complete a "pop" operation.
114  * @param queue Lockless queue instance
115  *
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.
118  */
119 static FLUID_INLINE void
120 fluid_ringbuffer_next_outptr (fluid_ringbuffer_t *queue)
121 {
122   fluid_atomic_int_add (&queue->count, -1);
123
124   if (++queue->out == queue->totalcount)
125     queue->out = 0;
126 }
127
128 #endif /* _FLUID_ringbuffer_H */