Marsyas  0.6.0-alpha
/usr/src/RPM/BUILD/marsyas-0.6.0/src/marsyas/realtime/stage.h
Go to the documentation of this file.
00001 /*
00002 ** Copyright (C) 1998-2013 George Tzanetakis <gtzan@cs.uvic.ca>
00003 **
00004 ** This program is free software; you can redistribute it and/or modify
00005 ** it under the terms of the GNU General Public License as published by
00006 ** the Free Software Foundation; either version 2 of the License, or
00007 ** (at your option) any later version.
00008 **
00009 ** This program 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 General Public License for more details.
00013 **
00014 ** You should have received a copy of the GNU General Public License
00015 ** along with this program; if not, write to the Free Software
00016 ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00017 */
00018 
00019 #ifndef MARSYAS_REALTIME_STAGE_INCLUDED
00020 #define MARSYAS_REALTIME_STAGE_INCLUDED
00021 
00022 #include <array>
00023 #include <atomic>
00024 
00025 namespace Marsyas {
00026 namespace RealTime {
00027 
00028 using std::array;
00029 using std::atomic_int;
00030 using std::atomic;
00031 
00056 template <typename T>
00057 class stage
00058 {
00059   struct item {
00060     bool valid;
00061     T data;
00062     item(): valid(false) {}
00063   };
00064 
00065   array<item, 3> m_items;
00066 
00067   atomic<int> m_stage_index;
00068   int m_back_index;
00069   int m_front_index;
00070 
00071 public:
00072   stage( const T & initial_value = T() ):
00073     m_stage_index(0),
00074     m_back_index(1),
00075     m_front_index(2)
00076   {
00077     clear(initial_value);
00078   }
00079 
00083   void clear( const T & initial_value = T() )
00084   {
00085     for (int i = 0; i < 3; ++i)
00086     {
00087       m_items[i].data = initial_value;
00088       m_items[i].valid = false;
00089     }
00090   }
00091 
00092   T & back()
00093   {
00094     return m_items[m_back_index].data;
00095   }
00096 
00097   void push()
00098   {
00099     m_items[m_back_index].valid = true;
00100     m_back_index = m_stage_index.exchange(m_back_index, std::memory_order_release);
00101   }
00102 
00103   bool has_front() const
00104   {
00105     return m_items[m_front_index].valid;
00106   }
00107 
00108   T & front()
00109   {
00110     if (!has_front())
00111       throw std::out_of_range("stage: Tried to access unavailable front.");
00112     return m_items[m_front_index].data;
00113   }
00114 
00115   void pop()
00116   {
00117     m_items[m_front_index].valid = false;
00118     m_front_index = m_stage_index.exchange(m_front_index, std::memory_order_acquire);
00119   }
00120 };
00121 
00122 }
00123 } // namespace Marsyas::RealTime
00124 
00125 #endif // MARSYAS_REALTIME_STAGE_INCLUDED