/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /*************************************************************************** * queue.h * * Tue Nov 9 10:57:20 CET 2004 * Copyright 2004 Bent Bisballe * deva@aasimon.org ****************************************************************************/ /* * Originally from: * RTVideoRec Realtime video recoder and encoder for Linux * * Copyright (C) 2004 B. Stultiens */ /* * This file is part of MIaV. * * MIaV is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * MIaV is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with MIaV; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ #ifndef __RTVIDEOREC_QUEUE_H #define __RTVIDEOREC_QUEUE_H #include #include #include #include //#include //#include #include "thread.h" #include "util.h" typedef struct __buf_t { struct __buf_t *next; struct __buf_t *prev; void *data; } buf_t; template class Queue { public: Queue(int glimit = 0); ~Queue(); void push(T *t); T *pop(); T *peek(); void lock(); void unlock(); int length(); private: volatile bool locked; int limit; buf_t *head; buf_t *tail; int count; pthread_mutex_t mutex; T *_pop(); }; /** * Initialize queue */ template Queue::Queue(int glimit) { locked = false; pthread_mutex_init (&mutex, NULL); limit = glimit; count = 0; head = NULL; tail = NULL; } /** * Clean up queue. */ template Queue::~Queue() { if(count != 0) { fprintf(stderr, "Queue not empty (%d)\n", count); while(T *t = _pop()) delete t; } pthread_mutex_destroy(&mutex); } /** * Push element on queue. */ template void Queue::push(T *t) { if(locked) { delete t; return; } pthread_mutex_lock(&mutex); buf_t *b = (buf_t*)xmalloc(sizeof(*b)); b->data = (void*)t; assert(b != NULL); if(limit && count > 0) { T* tmp = (T*)_pop(); delete tmp; } if(!head) { head = tail = b; b->next = b->prev = NULL; count = 1; pthread_mutex_unlock(&mutex); return; } b->next = tail; b->prev = NULL; if(tail) tail->prev = b; tail = b; count++; pthread_mutex_unlock(&mutex); } /** * Pop element from queue. * If queue is empty, NULL is returned. */ template T *Queue::pop() { pthread_mutex_lock(&mutex); T *d = _pop(); pthread_mutex_unlock(&mutex); return d; } /** * Pop helper method * If queue is empty, NULL is returned. */ template T *Queue::_pop() { T *d; buf_t *b; assert(count >= 0); if(count == 0) { return NULL; } b = head; if(b->prev) b->prev->next = NULL; head = b->prev; if(b == tail) tail = NULL; count--; d = (T*)b->data; free(b); return d; } /** * Peek foremost element in queue * If queue is empty, NULL is returned. */ template T *Queue::peek() { // pthread_mutex_lock(&mutex); T *d; // assert(count >= 0); if(count == 0) { return NULL; } d = (T*)head->data; // pthread_mutex_unlock(&mutex); return d; } /** * Print current length of queue */ template int Queue::length() { int length; pthread_mutex_lock(&mutex); length = count; pthread_mutex_unlock(&mutex); return length; } /** * Lock the queue (all elements pushed from this point will be deleted.) */ template void Queue::lock() { fprintf(stderr, "Lock this motherfucker..."); fflush(stderr); locked = true; fprintf(stderr, "done\n"); fflush(stderr); } /** * Unlock the queue. */ template void Queue::unlock() { fprintf(stderr, "Unlock this motherfucker..."); fflush(stderr); locked = false; fprintf(stderr, "done\n"); fflush(stderr); } #endif