S3FC project page | S3FC home page |
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 |
|