Habitat-lora-gateway/lifo_buffer.c

166 wiersze
3.3 KiB
C

#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "lifo_buffer.h"
void lifo_buffer_init(lifo_buffer_t *buf, uint32_t length)
{
pthread_mutex_init(&buf->Mutex, NULL);
pthread_cond_init(&buf->Signal, NULL);
pthread_mutex_lock(&buf->Mutex);
buf->Head = 0;
buf->Tail = 0;
buf->Length = length;
buf->Data = malloc(length * sizeof(void *));
buf->Quit = false;
pthread_mutex_unlock(&buf->Mutex);
}
uint32_t lifo_buffer_queued(lifo_buffer_t *buf)
{
uint32_t result;
pthread_mutex_lock(&buf->Mutex);
if(buf->Head >= buf->Tail)
{
result = buf->Head - buf->Tail;
}
else
{
result = buf->Head + (buf->Length - buf->Tail);
}
pthread_mutex_unlock(&buf->Mutex);
return result;
}
/* Lossy when buffer is full */
void lifo_buffer_push(lifo_buffer_t *buf, void *data_ptr)
{
pthread_mutex_lock(&buf->Mutex);
/* If no space, remove oldest from bottom of the queue by advancing Tail */
if(buf->Head==(buf->Tail-1) || (buf->Head==(buf->Length-1) && buf->Tail==0))
{
if(buf->Tail==(buf->Length-1))
buf->Tail=0;
else
buf->Tail++;
}
if(buf->Head==(buf->Length-1))
buf->Head=0;
else
buf->Head++;
buf->Data[buf->Head] = data_ptr;
pthread_cond_signal(&buf->Signal);
pthread_mutex_unlock(&buf->Mutex);
}
/* Returns NULL when unsuccessful */
void *lifo_buffer_pop(lifo_buffer_t *buf)
{
void *result;
pthread_mutex_lock(&buf->Mutex);
if(buf->Head!=buf->Tail)
{
result = buf->Data[buf->Head];
if(buf->Head==0)
buf->Head=(buf->Length-1);
else
buf->Head--;
pthread_mutex_unlock(&buf->Mutex);
}
else
{
pthread_mutex_unlock(&buf->Mutex);
result = NULL;
}
return result;
}
void *lifo_buffer_waitpop(lifo_buffer_t *buf)
{
void *result;
pthread_mutex_lock(&buf->Mutex);
while(buf->Head==buf->Tail && !buf->Quit) /* If buffer is empty */
{
/* Mutex is atomically unlocked on beginning waiting for signal */
pthread_cond_wait(&buf->Signal, &buf->Mutex);
/* and locked again on resumption */
}
if(buf->Quit)
{
return NULL;
}
result = buf->Data[buf->Head];
if(buf->Head==0)
buf->Head=(buf->Length-1);
else
buf->Head--;
pthread_mutex_unlock(&buf->Mutex);
return result;
}
void lifo_buffer_quitwait(lifo_buffer_t *buf)
{
pthread_mutex_lock(&buf->Mutex);
buf->Quit = true;
pthread_cond_signal(&buf->Signal);
pthread_mutex_unlock(&buf->Mutex);
}
/* Puts it on the bottom to avoid clogging by packet data problems, lossy when buffer is full */
bool lifo_buffer_requeue(lifo_buffer_t *buf, void *data_ptr)
{
bool result;
pthread_mutex_lock(&buf->Mutex);
/* If no space, ignore */
if(buf->Head!=(buf->Tail-1) && !(buf->Head==(buf->Length-1) && buf->Tail==0))
{
buf->Data[buf->Tail] = data_ptr;
if(buf->Tail==0)
buf->Tail=(buf->Length-1);
else
buf->Tail--;
pthread_cond_signal(&buf->Signal);
result = true;
}
else
{
result = false;
}
pthread_mutex_unlock(&buf->Mutex);
return result;
}