libGDF
RecordBuffer.cpp
00001 //
00002 // This file is part of libGDF.
00003 //
00004 // libGDF is free software: you can redistribute it and/or modify
00005 // it under the terms of the GNU Lesser General Public License as
00006 // published by the Free Software Foundation, either version 3 of
00007 // the License, or (at your option) any later version.
00008 //
00009 // libGDF is distributed in the hope that it will be useful,
00010 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012 // GNU Lesser General Public License for more details.
00013 //
00014 // You should have received a copy of the GNU Lesser General Public License
00015 // along with libGDF.  If not, see <http://www.gnu.org/licenses/>.
00016 //
00017 // Copyright 2010 Martin Billinger
00018 
00019 #include "GDF/RecordBuffer.h"
00020 #include "GDF/Record.h"
00021 #include "GDF/GDFHeaderAccess.h"
00022 #include "GDF/tools.h"
00023 //#include <iostream>
00024 
00025 namespace gdf
00026 {
00027     RecordBuffer::RecordBuffer( const GDFHeaderAccess *gdfh ) : m_gdfh(gdfh)
00028     {
00029         m_pool = NULL;
00030     }
00031 
00032     //===================================================================================================
00033     //===================================================================================================
00034 
00035     RecordBuffer::~RecordBuffer( )
00036     {
00037         clearBuffers( );
00038         if( m_pool )
00039             delete m_pool;
00040     }
00041 
00042     //===================================================================================================
00043     //===================================================================================================
00044 
00045     void RecordBuffer::clearBuffers( )
00046     {
00047         if( m_pool )
00048         {
00049             std::list<Record*>::iterator it = m_records.begin( );
00050             for( ; it != m_records.end(); it++ )
00051                 m_pool->push( *it );
00052 
00053             it = m_records_full.begin( );
00054             for( ; it != m_records_full.end(); it++ )
00055                 m_pool->push( *it );
00056         }
00057 
00058         m_records.clear( );
00059         m_records_full.clear( );
00060 
00061         m_num_full = 0;
00062     }
00063 
00064     //===================================================================================================
00065     //===================================================================================================
00066 
00067     void RecordBuffer::reset( )
00068     {
00069         size_t M = m_gdfh->getMainHeader_readonly( ).get_num_signals( );
00070         clearBuffers( );
00071         m_channelhead.resize( M );
00072         for( size_t i=0; i<M; i++ )
00073             m_channelhead[i] =m_records.begin( );
00074         if( m_pool )
00075             delete m_pool;
00076         m_pool = new PointerPool<Record>( Record(m_gdfh) );
00077     }
00078 
00079     //===================================================================================================
00080     //===================================================================================================
00081 
00082     void RecordBuffer::handleChannelFull( const size_t channel_idx )
00083     {
00084         //std::cout << "Channel Full" << std::endl;
00085         Record *r = *m_channelhead[channel_idx];
00086         m_channelhead[channel_idx]++;
00087         if( r->isFull() )
00088             handleRecordFull( );
00089     }
00090 
00091     //===================================================================================================
00092     //===================================================================================================
00093 
00094     void RecordBuffer::handleRecordFull( )
00095     {
00096         //std::cout << "Record Full" << std::endl;
00097         m_records_full.push_back( m_records.front() );
00098         m_records.pop_front( );
00099         m_num_full++;
00100 
00101         std::list<RecordFullHandler*>::iterator it = m_recfull_callbacks.begin( );
00102         for( ; it != m_recfull_callbacks.end(); it++ )
00103             (*it)->triggerRecordFull( m_records_full.back() );
00104     }
00105 
00106     //===================================================================================================
00107     //===================================================================================================
00108 
00109     void RecordBuffer::registerRecordFullCallback( RecordFullHandler *h )
00110     {
00111         m_recfull_callbacks.push_back( h );
00112     }
00113 
00114     //===================================================================================================
00115     //===================================================================================================
00116 
00117     void RecordBuffer::unregisterRecordFullCallback( RecordFullHandler *h )
00118     {
00119         m_recfull_callbacks.remove( h );
00120     }
00121 
00122     //===================================================================================================
00123     //===================================================================================================
00124 
00125     void RecordBuffer::addSamplePhys( const size_t channel_idx, const double value )
00126     {
00127         Channel *ch = getValidChannel( channel_idx );
00128         ch->addSamplePhys( value );
00129         if( ch->getFree( ) == 0 )
00130             handleChannelFull( channel_idx );
00131     }
00132 
00133     //===================================================================================================
00134     //===================================================================================================
00135 
00136     void RecordBuffer::blitSamplesPhys( const size_t channel_idx, const double *values, size_t num )
00137     {
00138         size_t i = 0;
00139         while( i<num )
00140         {
00141             Channel *ch = getValidChannel( channel_idx );
00142             size_t n = std::min( num-i, ch->getFree( ) );
00143             ch->blitSamplesPhys( &values[i], n );
00144             if( ch->getFree( ) == 0 )
00145                 handleChannelFull( channel_idx );
00146             i += n;
00147         }
00148     }
00149 
00150     //===================================================================================================
00151     //===================================================================================================
00152 
00153     void RecordBuffer::addRecord( Record *r )
00154     {
00155         if( getNumPartialRecords( ) > 0 )
00156             throw exception::invalid_operation( "RecordBuffer::addRecord called, but buffer contains partial records." );
00157         m_records_full.push_back( r );
00158         m_num_full++;
00159 
00160         std::list<RecordFullHandler*>::iterator it = m_recfull_callbacks.begin( );
00161         for( ; it != m_recfull_callbacks.end(); it++ )
00162             (*it)->triggerRecordFull( m_records_full.back() );
00163     }
00164 
00165     //===================================================================================================
00166     //===================================================================================================
00167 
00168     Record *RecordBuffer::acquireRecord( )
00169     {
00170         return m_pool->pop( );
00171     }
00172 
00173     //===================================================================================================
00174     //===================================================================================================
00175 
00176     std::list< Record* >::iterator RecordBuffer::createNewRecord( )
00177     {
00178         Record *r = m_pool->pop( );
00179         r->clear( );
00180         m_records.push_back( r );
00181         std::list< Record* >::iterator it = m_records.end( );
00182         it--;
00183         return it;
00184     }
00185 
00186     //===================================================================================================
00187     //===================================================================================================
00188 
00189     Record *RecordBuffer::getFirstFullRecord( )
00190     {
00191         if( m_num_full > 0 )
00192             return m_records_full.front( );
00193         else
00194             return NULL;
00195     }
00196 
00197     //===================================================================================================
00198     //===================================================================================================
00199 
00200     void RecordBuffer::removeFirstFullRecord( )
00201     {
00202         m_pool->push( m_records_full.front() );
00203         m_records_full.pop_front( );
00204         m_num_full--;
00205     }
00206 
00207     //===================================================================================================
00208     //===================================================================================================
00209 
00210     Channel *RecordBuffer::getValidChannel( const size_t channel_idx )
00211     {
00212         if( channel_idx >= m_channelhead.size( ) )
00213             throw exception::nonexistent_channel_access( "channel "+boost::lexical_cast<std::string>(channel_idx) +"does not exist" );
00214 
00215         if( m_channelhead[channel_idx] == m_records.end() )
00216         {
00217             if( m_records.size() > 0 )
00218             {
00219                 if( m_records.back()->getChannel(channel_idx)->getFree( ) == 0 )
00220                     m_channelhead[channel_idx] = createNewRecord( );
00221                 else
00222                     throw exception::corrupt_recordbuffer( "DOOM is upon us!" );
00223             }
00224             else
00225             {
00226                 // list was empty: set all channel heads to the new record.
00227                 std::list< Record* >::iterator r = createNewRecord( );
00228                 for( size_t i=0; i<m_channelhead.size(); i++ )
00229                     m_channelhead[i] = r;
00230             }
00231         }
00232 
00233         return (*m_channelhead[channel_idx])->getChannel( channel_idx );
00234     }
00235 
00236     //===================================================================================================
00237     //===================================================================================================
00238 
00239     size_t RecordBuffer::getNumFreeAlloc( const size_t channel_idx )
00240     {
00241         size_t num = 0;
00242         getValidChannel( channel_idx );
00243         std::list< Record* >::iterator it = m_channelhead[channel_idx];
00244         while( it != m_records.end() )
00245         {
00246             num += (*it)->getChannel( channel_idx )->getFree( );
00247             it ++;
00248         }
00249         return num;
00250     }
00251 
00252     //===================================================================================================
00253     //===================================================================================================
00254 
00255     void RecordBuffer::flood( )
00256     {
00257         while( getNumPartialRecords( ) > 0 )
00258         {
00259             m_records.front( )->fill( );
00260             handleRecordFull( );
00261         }
00262 
00263         for( size_t i=0; i<m_channelhead.size(); i++ )
00264             m_channelhead[i] =m_records.begin( );
00265     }
00266 
00267     //===================================================================================================
00268     //===================================================================================================
00269 
00270 }
 All Data Structures Functions Variables Friends