#include #include #include #include #include #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; }