S3FC project page S3FC home page

Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members   Related Pages  

s3_growable_fifo_queue.h

Go to the documentation of this file.
00001 /*
00002  * Stone Three Foundation Class (s3fc) provides a number of utility classes.
00003  * Copyright (C) 2001 by Stone Three Signal Processing (Pty) Ltd.
00004  *
00005  * Authored by Stone Three Signal Processing (Pty) Ltd.
00006  *
00007  * This library is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU Lesser General Public
00009  * License as published by the Free Software Foundation; either
00010  * version 2.1 of the License, or (at your option) any later version.
00011  * 
00012  * This library is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015  * Lesser General Public License for more details.
00016  * 
00017  * You should have received a copy of the GNU Lesser General Public
00018  * License along with this library; if not, write to the Free Software
00019  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00020  * 
00021  * Please see the file 'COPYING' in the source root directory.
00022  */
00023 
00030 #ifndef S3_GROWABLE_FIFO_QUEUE_H
00031 #define S3_GROWABLE_FIFO_QUEUE_H
00032 
00033 #include <pthread.h>
00034 #include <queue>
00035 #include <cassert>
00036 
00037 #include <s3fc/s3_fifo_base.h>
00038 #include <s3fc/s3_macros.h>
00039 
00049 template <typename T>
00050 class s3_growable_fifo_queue : public s3_fifo_base<T>
00051 {
00052   private:
00054    pthread_mutex_t mutex;
00055 
00057    pthread_mutexattr_t m_attr;
00058 
00064    pthread_cond_t cond_not_empty;
00065 
00070    pthread_cond_t cond_not_full;
00071 
00073    std::queue<T> q;
00074 
00080    int max_size;
00081    
00082   public:
00089    s3_growable_fifo_queue(int n_max_size = -1) :
00090       max_size(n_max_size)
00091    {
00092       pthread_mutexattr_init(&m_attr);
00093       pthread_mutex_init(&mutex, &m_attr);
00094       pthread_cond_init(&cond_not_empty, NULL);
00095       pthread_cond_init(&cond_not_full, NULL);
00096    }
00097    
00099    virtual ~s3_growable_fifo_queue()
00100    {
00101       pthread_mutexattr_destroy(&m_attr);
00102       pthread_mutex_destroy(&mutex);
00103       pthread_cond_destroy(&cond_not_empty);
00104       pthread_cond_destroy(&cond_not_full);
00105    }
00106    
00114    void push(const T& t)
00115    {
00116       // set unlock handler and lock the state
00117       pthread_cleanup_push(s3_fifo_base<T>::unlock_mutex, &mutex);
00118       pthread_mutex_lock(&mutex);
00119       // put assert in block as it is macro and may span several lines [rfanner]
00120       if (max_size !=-1)
00121       {
00122     assert((int)q.size() <= max_size);
00123       }
00124       while ((int)q.size() == max_size)
00125       {
00126     // Queue is full, so wait for the signal.
00127     pthread_cond_wait(&cond_not_full,&mutex);
00128       }
00129       pthread_cond_signal(&cond_not_empty);
00130       // If we blocked on queue full, the queue will be full after this.
00131       q.push(t); 
00132       s3_fifo_base<T>::notify_consumers();   // let all the consumers know
00133       pthread_cleanup_pop(0);
00134       pthread_mutex_unlock(&mutex);
00135    }
00136    
00146    T pop()
00147    {
00148       T t;
00149       // set unlock handler and lock the state
00150       pthread_cleanup_push(s3_fifo_base<T>::unlock_mutex, &mutex);
00151       // We are gonna wait here until something arrives.
00152       pthread_mutex_lock(&mutex);
00153       if (max_size !=-1) assert((int)q.size() <= max_size);
00154 
00155       while ( q.empty() )
00156       {
00157     assert((int)q.size() == 0);
00158     // Release lock and wait on condition.
00159     pthread_cond_wait(&cond_not_empty,&mutex);
00160       }
00161 
00162       // Always signal "Not full" because it will always be true. This
00163       // Eliminates deadlocks caused by both consumers and producers
00164       // waiting on signals that will never come.
00165       pthread_cond_signal(&cond_not_full);
00166       
00167       t=q.front();
00168       assert(!q.empty());
00169       q.pop();
00170       s3_fifo_base<T>::notify_producers();   // let all the producers know
00171       pthread_cleanup_pop(0);
00172       pthread_mutex_unlock(&mutex);
00173       return t;
00174    }
00175    
00181    bool empty() const
00182    {
00183       bool res;
00184       pthread_mutex_lock(NONCONST_MUTEXP(&mutex));
00185       res = q.empty();
00186       pthread_mutex_unlock(NONCONST_MUTEXP(&mutex));
00187       return res;
00188    }
00189 
00194    bool full() const
00195    {
00196       bool res;
00197       pthread_mutex_lock(NONCONST_MUTEXP(&mutex));
00198       res = ((int)q.size() == max_size);
00199       pthread_mutex_unlock(NONCONST_MUTEXP(&mutex));
00200       return res;
00201    }
00202    
00206    unsigned int size() const
00207    {
00208       unsigned int s;
00209       pthread_mutex_lock(NONCONST_MUTEXP(&mutex));
00210       s = q.size();
00211       pthread_mutex_unlock(NONCONST_MUTEXP(&mutex));
00212       return s;
00213       
00214    }
00215    
00216 };   
00217 
00218 #endif

Send comments to: s3fc@stonethree.com SourceForge Logo