00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00033 #include <s3fc/s3_inplace_fifo_mux.h>
00034 #include <s3fc/s3_exception.h>
00035 #include <s3fc/s3_macros.h>
00036 #include <algorithm>
00037
00038
00039 template<typename T>
00040 s3_inplace_fifo_mux<T>::stub_queue::stub_queue(
00041 s3_inplace_fifo_mux<T>* n_mux) :
00042 mux(n_mux)
00043 {
00044 }
00045
00046
00047 template<typename T>
00048 bool s3_inplace_fifo_mux<T>::stub_queue::empty() const
00049 {
00050
00051 CONST_OVERRIDE_THIS(s3_inplace_fifo_mux<T>::stub_queue) lock_select();
00052 bool ef = mux->queue->empty();
00053 CONST_OVERRIDE_THIS(s3_inplace_fifo_mux<T>::stub_queue) unlock_next();
00054 return ef;
00055 }
00056
00057
00058 template<typename T>
00059 bool s3_inplace_fifo_mux<T>::stub_queue::full() const
00060 {
00061
00062 CONST_OVERRIDE_THIS(s3_inplace_fifo_mux<T>::stub_queue) lock_select();
00063 bool ff = mux->queue->full();
00064 CONST_OVERRIDE_THIS(s3_inplace_fifo_mux<T>::stub_queue) unlock_next();
00065 return ff;
00066 }
00067
00068
00069
00070 template<typename T>
00071 unsigned int s3_inplace_fifo_mux<T>::stub_queue::size() const
00072 {
00073
00074 CONST_OVERRIDE_THIS(s3_inplace_fifo_mux<T>::stub_queue) lock_select();
00075 unsigned int s = mux->queue->size();
00076 CONST_OVERRIDE_THIS(s3_inplace_fifo_mux<T>::stub_queue) unlock_next();
00077 return s;
00078 }
00079
00080
00081 template<typename T>
00082 void s3_inplace_fifo_mux<T>::stub_queue::push(const T& t)
00083 {
00084
00085 lock_select();
00086 mux->queue->push(t);
00087 unlock_next();
00088 }
00089
00090
00091 template<typename T>
00092 T s3_inplace_fifo_mux<T>::stub_queue::pop()
00093 {
00094 T t;
00095
00096 lock_select();
00097 t = mux->queue->pop();
00098 unlock_next();
00099 return t;
00100 }
00101
00102
00103 template<typename T>
00104 T* s3_inplace_fifo_mux<T>::stub_queue::open_input()
00105 {
00106 T* t;
00107
00108 lock_select();
00109 t = mux->queue->open_input();
00110 unlock_next();
00111 return t;
00112 }
00113
00114
00115 template<typename T>
00116 T* s3_inplace_fifo_mux<T>::stub_queue::nbl_open_input()
00117 {
00118 T* t;
00119
00120 lock_select();
00121 t = mux->queue->nbl_open_input();
00122 unlock_next();
00123 return t;
00124 }
00125
00126
00127 template<typename T>
00128 void s3_inplace_fifo_mux<T>::stub_queue::close_input(const T* t)
00129 {
00130
00131 mux->queue->close_input(t);
00132 }
00133
00134
00135 template<typename T>
00136 T* s3_inplace_fifo_mux<T>::stub_queue::open_output()
00137 {
00138 T* t;
00139
00140 lock_select();
00141 t = mux->queue->open_output();
00142 unlock_next();
00143 return t;
00144 }
00145
00146
00147 template<typename T>
00148 T* s3_inplace_fifo_mux<T>::stub_queue::nbl_open_output()
00149 {
00150 T* t;
00151
00152 lock_select();
00153 t = mux->queue->nbl_open_output();
00154 unlock_next();
00155 return t;
00156 }
00157
00158
00159 template<typename T>
00160 void s3_inplace_fifo_mux<T>::stub_queue::close_output(const T* t)
00161 {
00162
00163 mux->queue->close_output(t);
00164 }
00165
00166
00167 template<typename T>
00168 void s3_inplace_fifo_mux<T>::stub_queue::lock_select()
00169 {
00170 mux->state_lock.lock();
00171
00172 if ( mux->vqueue_list[mux->current_idx] != this )
00173 {
00174
00175 waiter.wait(mux->state_lock);
00176 }
00177 }
00178
00179
00180 template<typename T>
00181 void s3_inplace_fifo_mux<T>::stub_queue::unlock_next()
00182 {
00183
00184 if ( mux->auto_select )
00185 {
00186
00187 mux->current_idx = (mux->current_idx + 1) % (mux->vqueue_list.size());
00188
00189 mux->vqueue_list[mux->current_idx]->waiter.broadcast();
00190 }
00191 mux->state_lock.unlock();
00192 }
00193
00194
00195 template<typename T>
00196 s3_inplace_fifo_mux<T>::s3_inplace_fifo_mux() :
00197 queue(0),
00198 vqueue_list(0),
00199 current_idx(0),
00200 started(false),
00201 auto_select(true)
00202 {
00203 }
00204
00205
00206 template<typename T>
00207 s3_inplace_fifo_mux<T>::~s3_inplace_fifo_mux()
00208 {
00209 for (typename std::vector<stub_queue*>::iterator ptr = vqueue_list.begin();
00210 ptr != vqueue_list.end();
00211 ptr++)
00212 {
00213 delete *ptr;
00214 }
00215 }
00216
00217
00218 template<typename T>
00219 void s3_inplace_fifo_mux<T>::start()
00220 {
00221 state_lock.lock();
00222 if ( started == true )
00223 {
00224 state_lock.unlock();
00225 throw s3_generic_exception(
00226 "s3_inplace_fifo_mux<T>::start()",
00227 "already started");
00228 }
00229 started = true;
00230 state_lock.unlock();
00231 }
00232
00233
00234 template<typename T>
00235 void s3_inplace_fifo_mux<T>::stop()
00236 {
00237 state_lock.lock();
00238 if ( started == false )
00239 {
00240 state_lock.unlock();
00241 throw s3_generic_exception(
00242 "s3_inplace_fifo_mux<T>::stop()",
00243 "already stopped");
00244 }
00245 started = false;
00246 state_lock.unlock();
00247 }
00248
00249
00250 template<typename T>
00251 bool s3_inplace_fifo_mux<T>::is_started() const
00252 {
00253 bool s;
00254 state_lock.lock();
00255 s = started;
00256 state_lock.unlock();
00257 return s;
00258 }
00259
00260
00261 template<typename T>
00262 s3_inplace_fifo_base<T>& s3_inplace_fifo_mux<T>::create_vqueue()
00263 {
00264 state_lock.lock();
00265 if ( started == true )
00266 {
00267 state_lock.unlock();
00268 throw s3_generic_exception(
00269 "s3_inplace_fifo_mux<T>::create_vqueue()",
00270 "attempt to create_vqueue on started mux");
00271 }
00273 s3_inplace_fifo_mux<T>::stub_queue* q = new stub_queue(this);
00274 vqueue_list.push_back(q);
00275 state_lock.unlock();
00276 return *q;
00277 }
00278
00279
00280 template<typename T>
00281 void s3_inplace_fifo_mux<T>::destroy_vqueue(const s3_inplace_fifo_base<T>& q)
00282 {
00283 state_lock.lock();
00284 if ( started == true )
00285 {
00286 state_lock.unlock();
00287 throw s3_generic_exception(
00288 "s3_inplace_fifo_mux<T>::destroy_vqueue()",
00289 "attempt to invoke on started mux");
00290 }
00291 #if 0
00292
00293 const stub_queue<T>* qp = dynamic_cast<const stub_queue<T>*>(&q);
00294 if ( qp == 0 )
00295 {
00296 state_lock.unlock();
00297 throw s3_generic_exception(
00298 "s3_inplace_fifo_mux<T>::destroy_vqueue()",
00299 "q is not an s3_inplace_fifo_mux<T>::stub_queue instance.");
00300 }
00301 #else
00302 const s3_inplace_fifo_mux<T>::stub_queue* qp =
00303 reinterpret_cast<const s3_inplace_fifo_mux<T>::stub_queue*>(&q);
00304 #endif
00305 typename std::vector<s3_inplace_fifo_mux<T>::stub_queue*>::iterator iter =
00306 std::find(vqueue_list.begin(), vqueue_list.end(), qp);
00307 if ( iter == vqueue_list.end() )
00308 {
00309 state_lock.unlock();
00310 throw s3_generic_exception(
00311 "s3_inplace_fifo_mux<T>::destroy_vqueue()",
00312 "virtual queue list does not contain specified entry.");
00313 }
00314 vqueue_list.erase(iter);
00315 state_lock.unlock();
00316 }
00317
00318 #if 0
00319
00320 template<typename T>
00321 void s3_inplace_fifo_mux<T>::select_vqueue(const s3_inplace_fifo_base<T>& vq)
00322 {
00323 state_lock.lock();
00324
00325 if ( started == true && auto_select == true )
00326 {
00327 state_lock.unlock();
00328 throw s3_generic_exception(
00329 "s3_inplace_fifo_mux<T>::select_vqueue()",
00330 "attempt to invoke on started auto-selecting mux");
00331 }
00332
00333 const s3_inplace_fifo_mux<T>::stub_queue* qp =
00334 dynamic_cast<const s3_inplace_fifo_mux<T>::stub_queue*>(&vq);
00335 if ( qp == 0 )
00336 {
00337 state_lock.unlock();
00338 throw s3_generic_exception(
00339 "s3_inplace_fifo_mux<T>::select_vqueue()",
00340 "q is not an s3_inplace_fifo_mux<T>::stub_queue instance.");
00341 }
00342 typename vector<stub_queue<T>*>::iterator iter = find(
00343 vqueue_list.begin(), vqueue_list.end(), qp);
00344 if ( iter == vqueue_list.end() )
00345 {
00346 state_lock.unlock();
00347 throw s3_generic_exception(
00348 "s3_inplace_fifo_mux<T>::select_vqueue()",
00349 "virtual queue list does not contain specified entry.");
00350 }
00351 current_idx = iter - vqueue_list.begin();
00352 state_lock.unlock();
00353 }
00354 #endif
00355
00356
00357 template<typename T>
00358 void s3_inplace_fifo_mux<T>::set_queue(s3_inplace_fifo_base<T>& q)
00359 {
00360 state_lock.lock();
00361 if ( started == true )
00362 {
00363 state_lock.unlock();
00364 throw s3_generic_exception(
00365 "s3_inplace_fifo_mux<T>::set_queue()",
00366 "attempt to invoke on started auto-selecting mux");
00367 }
00368 queue = &q;
00369 state_lock.unlock();
00370 }
00371
00372 #if 0
00373
00374 template<typename T>
00375 void s3_inplace_fifo_mux<T>::set_auto_select(bool n_val)
00376 {
00377 state_lock.lock();
00378 if ( started == true )
00379 {
00380 state_lock.unlock();
00381 throw s3_generic_exception(
00382 "s3_inplace_fifo_mux<T>::set_queue()",
00383 "attempt to invoke on started auto-selecting mux");
00384 }
00385 auto_select = n_val;
00386 state_lock.unlock();
00387 }
00388 #endif
00389