Path: blob/master/libs/fluidsynth/src/utils/fluid_ringbuffer.h
4396 views
/* FluidSynth - A Software Synthesizer1*2* Copyright (C) 2003 Peter Hanappe and others.3*4* This library is free software; you can redistribute it and/or5* modify it under the terms of the GNU Lesser General Public License6* as published by the Free Software Foundation; either version 2.1 of7* the License, or (at your option) any later version.8*9* This library is distributed in the hope that it will be useful, but10* WITHOUT ANY WARRANTY; without even the implied warranty of11* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU12* Lesser General Public License for more details.13*14* You should have received a copy of the GNU Lesser General Public15* License along with this library; if not, write to the Free16* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA17* 02110-1301, USA18*/1920#ifndef _FLUID_RINGBUFFER_H21#define _FLUID_RINGBUFFER_H2223#include "fluid_sys.h"2425/*26* Lockless event queue instance.27*/28struct _fluid_ringbuffer_t29{30char *array; /**< Queue array of arbitrary size elements */31int totalcount; /**< Total count of elements in array */32fluid_atomic_int_t count; /**< Current count of elements */33int in; /**< Index in queue to store next pushed element */34int out; /**< Index in queue of next popped element */35size_t elementsize; /**< Size of each element */36void *userdata;37};3839typedef struct _fluid_ringbuffer_t fluid_ringbuffer_t;404142fluid_ringbuffer_t *new_fluid_ringbuffer(int count, size_t elementsize);43void delete_fluid_ringbuffer(fluid_ringbuffer_t *queue);4445/**46* Get pointer to next input array element in queue.47* @param queue Lockless queue instance48* @param offset Normally zero, or more if you need to push several items at once49* @return Pointer to array element in queue to store data to or NULL if queue is full50*51* This function along with fluid_ringbuffer_next_inptr() form a queue "push"52* operation and is split into 2 functions to avoid an element copy. Note that53* the returned array element pointer may contain the data of a previous element54* if the queue has wrapped around. This can be used to reclaim pointers to55* allocated memory, etc.56*/57static FLUID_INLINE void *58fluid_ringbuffer_get_inptr(fluid_ringbuffer_t *queue, int offset)59{60return fluid_atomic_int_get(&queue->count) + offset >= queue->totalcount ? NULL61: queue->array + queue->elementsize * ((queue->in + offset) % queue->totalcount);62}6364/**65* Advance the input queue index to complete a "push" operation.66* @param queue Lockless queue instance67* @param count Normally one, or more if you need to push several items at once68*69* This function along with fluid_ringbuffer_get_inptr() form a queue "push"70* operation and is split into 2 functions to avoid element copy.71*/72static FLUID_INLINE void73fluid_ringbuffer_next_inptr(fluid_ringbuffer_t *queue, int count)74{75fluid_atomic_int_add(&queue->count, count);7677queue->in += count;7879if(queue->in >= queue->totalcount)80{81queue->in -= queue->totalcount;82}83}8485/**86* Get amount of items currently in queue87* @param queue Lockless queue instance88* @return amount of items currently in queue89*/90static FLUID_INLINE int91fluid_ringbuffer_get_count(fluid_ringbuffer_t *queue)92{93return fluid_atomic_int_get(&queue->count);94}959697/**98* Get pointer to next output array element in queue.99* @param queue Lockless queue instance100* @return Pointer to array element data in the queue or NULL if empty, can only101* be used up until fluid_ringbuffer_next_outptr() is called.102*103* This function along with fluid_ringbuffer_next_outptr() form a queue "pop"104* operation and is split into 2 functions to avoid an element copy.105*/106static FLUID_INLINE void *107fluid_ringbuffer_get_outptr(fluid_ringbuffer_t *queue)108{109return fluid_ringbuffer_get_count(queue) == 0 ? NULL110: queue->array + queue->elementsize * queue->out;111}112113114/**115* Advance the output queue index to complete a "pop" operation.116* @param queue Lockless queue instance117*118* This function along with fluid_ringbuffer_get_outptr() form a queue "pop"119* operation and is split into 2 functions to avoid an element copy.120*/121static FLUID_INLINE void122fluid_ringbuffer_next_outptr(fluid_ringbuffer_t *queue)123{124fluid_atomic_int_add(&queue->count, -1);125126if(++queue->out == queue->totalcount)127{128queue->out = 0;129}130}131132#endif /* _FLUID_ringbuffer_H */133134135