S3FC project page S3FC home page

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

s3_inplace_fifo_mux.tcc

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 
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    // lock, wait, forward, unlock
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    // lock, wait, forward, unlock
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 // CONST_OVERRIDE_THIS(x) const_cast<x*>(this)->
00068 
00069 //
00070 template<typename T>
00071 unsigned int s3_inplace_fifo_mux<T>::stub_queue::size() const
00072 {
00073    // lock, wait, forward, unlock
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    // lock, wait, forward, unlock
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    // lock, wait, forward, unlock
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    // lock, wait, forward, unlock
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    // lock, wait, forward, unlock
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    // forward
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    // lock, wait, forward, unlock
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    // lock, wait, forward, unlock
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    // forward
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    // am I NOT currently selected ?
00172    if ( mux->vqueue_list[mux->current_idx] != this )
00173    {
00174       // unlock lock and wait until I get selected
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    // auto-select enabled ?
00184    if ( mux->auto_select )
00185    {
00186       // advance to next queue in list
00187       mux->current_idx = (mux->current_idx + 1) % (mux->vqueue_list.size());
00188       // notify newly selected queue
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    // dynamic cast down and check
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    // check state
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    // dynamic cast down and check
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 

Send comments to: s3fc@stonethree.com SourceForge Logo