Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
wine-mirror
GitHub Repository: wine-mirror/wine
Path: blob/master/libs/fluidsynth/src/utils/fluid_ringbuffer.h
4396 views
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 Lesser General Public License
7
* as published by the Free Software Foundation; either version 2.1 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
* Lesser General Public License for more details.
14
*
15
* You should have received a copy of the GNU Lesser 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
fluid_atomic_int_t 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
size_t 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, size_t 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 offset 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
80
if(queue->in >= queue->totalcount)
81
{
82
queue->in -= queue->totalcount;
83
}
84
}
85
86
/**
87
* Get amount of items currently in queue
88
* @param queue Lockless queue instance
89
* @return amount of items currently in queue
90
*/
91
static FLUID_INLINE int
92
fluid_ringbuffer_get_count(fluid_ringbuffer_t *queue)
93
{
94
return fluid_atomic_int_get(&queue->count);
95
}
96
97
98
/**
99
* Get pointer to next output array element in queue.
100
* @param queue Lockless queue instance
101
* @return Pointer to array element data in the queue or NULL if empty, can only
102
* be used up until fluid_ringbuffer_next_outptr() is called.
103
*
104
* This function along with fluid_ringbuffer_next_outptr() form a queue "pop"
105
* operation and is split into 2 functions to avoid an element copy.
106
*/
107
static FLUID_INLINE void *
108
fluid_ringbuffer_get_outptr(fluid_ringbuffer_t *queue)
109
{
110
return fluid_ringbuffer_get_count(queue) == 0 ? NULL
111
: queue->array + queue->elementsize * queue->out;
112
}
113
114
115
/**
116
* Advance the output queue index to complete a "pop" operation.
117
* @param queue Lockless queue instance
118
*
119
* This function along with fluid_ringbuffer_get_outptr() form a queue "pop"
120
* operation and is split into 2 functions to avoid an element copy.
121
*/
122
static FLUID_INLINE void
123
fluid_ringbuffer_next_outptr(fluid_ringbuffer_t *queue)
124
{
125
fluid_atomic_int_add(&queue->count, -1);
126
127
if(++queue->out == queue->totalcount)
128
{
129
queue->out = 0;
130
}
131
}
132
133
#endif /* _FLUID_ringbuffer_H */
134
135