git stults online alsa-signals / master ring_buffer.c
master

Tree @master (Download .tar.gz)

ring_buffer.c @masterraw · history · blame

#include <pthread.h>
#include "ring_buffer.h"

typedef struct ring_buffer_t
{
  unsigned char  *data;
  size_t          readidx;
  size_t          writeidx;
  size_t          bytes;
  size_t          writebytes;
  pthread_mutex_t lock;
} ring_buffer_t;

ring_buffer_t *ring_buffer_create (size_t bytes)
{
  ring_buffer_t *rb;

  if ((rb = calloc (1, sizeof(ring_buffer_t))) == NULL)
    return NULL;

  if ((rb->data = calloc (bytes, sizeof(unsigned char))) == NULL)
    {
      free (rb);
      return NULL;
    }

  rb->bytes      = bytes;
  rb->writebytes = bytes;
  rb->readidx    = 0;
  rb->writeidx   = 0;
  pthread_mutex_init (&rb->lock, NULL);

  return rb;
}

void ring_buffer_destroy (ring_buffer_t *rb)
{
  if (rb == NULL)
    return;
  pthread_mutex_destroy (&rb->lock);
  free (rb->data);
  free (rb);
  rb = NULL;
  return;
}

size_t ring_buffer_read (ring_buffer_t *rb, unsigned char *data, size_t bytes)
{
  size_t readbytes;

  if (rb == NULL || data == NULL || bytes == 0)
    return 0;   

  if (pthread_mutex_trylock (&rb->lock))
    return 0;

  readbytes = rb->bytes - rb->writebytes;
  bytes     = (bytes > readbytes) ? readbytes : bytes;

  if (bytes > rb->bytes - rb->readidx)
    {
      size_t inc = rb->bytes - rb->readidx;
      memcpy (data,       rb->data + rb->readidx, inc);
      memcpy (data + inc, rb->data              , bytes - inc);
    }
  else
    memcpy (data, rb->data + rb->readidx, bytes);

  rb->readidx     = (rb->readidx + bytes) % rb->bytes;
  rb->writebytes += bytes;
  
  pthread_mutex_unlock (&rb->lock);

  return bytes;
}

size_t ring_buffer_write (ring_buffer_t *rb, unsigned char *data, size_t bytes)
{
  if (rb == NULL || data == NULL || bytes == 0)
    return 0;

  if (pthread_mutex_trylock (&rb->lock))
    return 0;
  
  bytes = (bytes > rb->writebytes) ? rb->writebytes : bytes;

  if (bytes > rb->bytes - rb->writeidx)
    {
      size_t inc = rb->bytes - rb->writeidx;
      memcpy (rb->data + rb->writeidx, data,       inc);
      memcpy (rb->data,                data + inc, bytes - inc);
    }
  else
    memcpy (rb->data + rb->writeidx, data, bytes);

  rb->writeidx    = (rb->writeidx + bytes) % rb->bytes;
  rb->writebytes -= bytes;

  if (pthread_mutex_unlock (&rb->lock))
    return 0;
  
  return bytes;
}
				    
size_t ring_buffer_size (ring_buffer_t *rb)
{
  if (rb == NULL)
    return 0;

  return rb->bytes;
}
				    
size_t ring_buffer_read_avail  (ring_buffer_t *rb)
{
  if (rb == NULL)
    return 0;

  return rb->bytes - rb->writebytes;
}

size_t ring_buffer_write_avail (ring_buffer_t *rb)
{
  if (rb == NULL)
    return 0;

  return rb->writebytes;
}

void ring_buffer_clear (ring_buffer_t *rb)
{
  if (rb == NULL)
    return;

  if (pthread_mutex_trylock (&rb->lock))
    return;

  memset (rb->data, 0x00, rb->bytes);
  rb->writebytes = rb->bytes;
  rb->readidx    = 0;
  rb->writeidx   = 0;

  pthread_mutex_unlock (&rb->lock);

  return;
}