Marsyas
0.6.0-alpha
|
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