00001 /* Copyright (C) 2000 KOM/Darmstadt University of Technology 00002 * 00003 * You are allowed to use all other parts of the code under the following terms: 00004 * 00005 * For non-commercial use, code may be used in unmodified form provided 00006 * that this copyright notice and this permission notice appear in 00007 * supporting documentation. 00008 * 00009 * This software is provided "as is" and without any express or implied 00010 * warranties, including, without limitation, the implied warranty of 00011 * fitness for a particular purpose. 00012 * 00013 * The code may be subjected to the GNU General Public License, Version 2, 00014 * and re-distributed under the terms of this license. 00015 * As a special exception, permission is granted to link this code 00016 * with the Qt library and distribute executables, as long as you 00017 * follow the requirements of the GNU GPL in regard to all of the 00018 * software in the executable aside from Qt. 00019 * 00020 * Commercial use other than under the terms of the GNU General Public 00021 * License is allowed only after express negotiation of conditions 00022 * with the authors. 00023 */ 00024 #ifndef OS_MNPCLIST_H 00025 #define OS_MNPCLIST_H 00026 00027 #include "MNList.h" 00028 #include "MNMutex.h" 00029 #include "MNSem.h" 00030 #include "MNProtectedVar.h" 00031 00032 #define PCLIST_NORMALMODE 00033 00034 /************************************************************* 00035 * MNPCList 00036 *************************************************************/ 00037 00038 template <class T> class MNPCList : private MNList<T> 00039 { 00040 bool _locked; 00041 MNMutex _lock; 00042 #ifdef PCLIST_NORMALMODE 00043 MNSem _sem; 00044 #else 00045 MNSemDebug _sem; 00046 #endif 00047 00048 public: 00049 MNPCList ( const MNPCList<T>& orig ) 00050 : MNList<T>(orig) 00051 , _locked(false) 00052 #ifndef PCLIST_NORMALMODE 00053 , _sem( "MNPCList<T>" ) 00054 #endif 00055 { 00056 } 00057 00058 MNPCList ( ) 00059 : _locked(false) 00060 #ifndef PCLIST_NORMALMODE 00061 , _sem( "MNPCList<T>" ) 00062 #endif 00063 { 00064 } 00065 00066 ~MNPCList ( ) 00067 { 00068 } 00069 00070 MNPCList<T>& operator=( const MNPCList<T>& orig ) 00071 { 00072 lock(); 00073 MNList<T>::operator=(orig); 00074 unlock(); 00075 return *this; 00076 } 00077 00078 inline bool empty() 00079 { 00080 lock(); 00081 bool ret = MNList<T>::empty(); 00082 unlock(); 00083 return ret; 00084 } 00085 inline int length() 00086 { 00087 lock(); 00088 int ret = MNList<T>::length(); 00089 unlock(); 00090 return ret; 00091 } 00092 00093 /* 00094 * T& peek_front(), T& peek_back and T& peek_here can not be 00095 * implemented with producer-consumer lists 00096 */ 00097 inline T peek_front() 00098 { 00099 lock(); 00100 T ret = MNList<T>::peek_front(); 00101 unlock(); 00102 return ret; 00103 } 00104 inline T peek_back() 00105 { 00106 lock(); 00107 T ret = MNList<T>::peek_back(); 00108 unlock(); 00109 return ret; 00110 } 00111 00112 /* 00113 * T& inf() can not be 00114 * implemented with producer-consumer lists 00115 */ 00116 inline T inf(void* r) 00117 { 00118 lock(); 00119 T ret = MNList<T>::inf(r); 00120 unlock(); 00121 return ret; 00122 } 00123 00124 inline void del_front() 00125 { 00126 lock(); 00127 MNList<T>::del_front(); 00128 unlock(); 00129 } 00130 inline void del_back() 00131 { 00132 lock(); 00133 MNList<T>::del_back(); 00134 unlock(); 00135 } 00136 inline void clear() 00137 { 00138 lock(); 00139 MNList<T>::clear(); 00140 unlock(); 00141 } 00142 00143 inline T pop() 00144 { 00145 lock(); 00146 T ret = MNList<T>::pop(); 00147 unlock(); 00148 return ret; 00149 } 00150 00151 inline void push_front( T x ) 00152 { 00153 lock(); 00154 MNList<T>::push_front(x); 00155 unlock(); 00156 } 00157 inline void prepend( T x ) 00158 { 00159 lock(); 00160 MNList<T>::prepend(x); 00161 unlock(); 00162 } 00163 inline void push_back( T x ) 00164 { 00165 lock(); 00166 MNList<T>::push_back(x); 00167 unlock(); 00168 } 00169 inline void append( T x ) 00170 { 00171 lock(); 00172 MNList<T>::append(x); 00173 unlock(); 00174 } 00175 00176 /* 00177 * These are special functions for consumers and produders. 00178 * They manipulate the semaphore as well as the lock. 00179 */ 00180 00181 inline void signal() 00182 { 00183 _sem.signal(); 00184 } 00185 00186 inline void wait() 00187 { 00188 assert ( _locked == true ); 00189 _locked = false; 00190 _sem.wait(_lock); 00191 _locked = true; 00192 } 00193 00194 inline T consumer_pop() 00195 { 00196 lock(); 00197 while ( locked_empty() ) wait(); 00198 T ret = MNList<T>::pop(); 00199 unlock(); 00200 return ret; 00201 } 00202 00203 inline bool consumer_pop( T& ret, ProtectedBool& terminate ) 00204 { 00205 lock(); 00206 do 00207 { 00208 if ( locked_empty() ) wait(); 00209 if ( !locked_empty() && terminate==false ) 00210 { 00211 ret = MNList<T>::pop(); 00212 unlock(); 00213 return true; 00214 } 00215 } 00216 while ( terminate==false ); 00217 unlock(); 00218 return false; 00219 } 00220 00221 inline void producer_push_front( T x ) 00222 { 00223 lock(); 00224 MNList<T>::push_front(x); 00225 signal(); 00226 unlock(); 00227 } 00228 inline void producer_prepend( T x ) 00229 { 00230 lock(); 00231 MNList<T>::prepend(x); 00232 signal(); 00233 unlock(); 00234 } 00235 inline void producer_push_back( T x ) 00236 { 00237 lock(); 00238 MNList<T>::push_back(x); 00239 signal(); 00240 unlock(); 00241 } 00242 inline void producer_append( T x ) 00243 { 00244 lock(); 00245 MNList<T>::append(x); 00246 signal(); 00247 unlock(); 00248 } 00249 00250 /* 00251 * Special functions that are used with manual locking. 00252 * This makes certainly sense when you look something up in a 00253 * list, and want to perform an operation based on the item 00254 * pointer. 00255 */ 00256 00257 inline void lock() 00258 { 00259 _lock.lock(); 00260 assert ( _locked == false ); 00261 _locked = true; // this is obviously not safe, should be the TID 00262 // but this is much cheaper for testing 00263 } 00264 00265 inline void unlock() 00266 { 00267 assert ( _locked == true ); 00268 _locked = false; 00269 _lock.unlock(); 00270 } 00271 00272 inline void* locked_first() const 00273 { 00274 assert ( _locked == true ); 00275 return MNList<T>::first(); 00276 } 00277 inline void* locked_last() const 00278 { 00279 assert ( _locked == true ); 00280 return MNList<T>::last(); 00281 } 00282 inline void* locked_pred(void* item) const 00283 { 00284 assert ( _locked == true ); 00285 return MNList<T>::pred(item); 00286 } 00287 inline void* locked_succ(void* item) const 00288 { 00289 assert ( _locked == true ); 00290 return MNList<T>::succ(item); 00291 } 00292 inline bool locked_empty() const 00293 { 00294 assert ( _locked == true ); 00295 return MNList<T>::empty(); 00296 } 00297 00298 inline T locked_pop() 00299 { 00300 T ret = MNList<T>::pop(); 00301 return ret; 00302 } 00303 00304 inline void locked_append( T x ) 00305 { 00306 assert ( _locked == true ); 00307 MNList<T>::append(x); 00308 } 00309 00310 inline T locked_inf(void* r) 00311 { 00312 assert ( _locked == true ); 00313 return MNList<T>::inf(r); 00314 } 00315 00316 inline void locked_del_item(void* item) 00317 { 00318 assert ( _locked == true ); 00319 MNList<T>::del_item(item); 00320 } 00321 00322 inline void locked_ins_before( void* x, T y ) 00323 { 00324 assert ( _locked == true ); 00325 MNList<T>::ins_before(x,y); 00326 } 00327 00328 inline void ins_after( void* x, T y ) 00329 { 00330 assert ( _locked == true ); 00331 MNList<T>::ins_after(x,y); 00332 } 00333 }; 00334 00335 #endif /* OS_MNPCLIST_H */ 00336