QtPdCom  1.4.1
ValueRing.h
Go to the documentation of this file.
1 /*****************************************************************************
2  *
3  * Copyright (C) 2009 - 2012 Florian Pose <fp@igh-essen.com>
4  *
5  * This file is part of the QtPdCom library.
6  *
7  * The QtPdCom library is free software: you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public License as
9  * published by the Free Software Foundation, either version 3 of the License,
10  * or (at your option) any later version.
11  *
12  * The QtPdCom library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
15  * General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public License
18  * along with the QtPdCom Library. If not, see
19  * <http://www.gnu.org/licenses/>.
20  *
21  ****************************************************************************/
22 
23 #ifndef PD_VALUERING_H
24 #define PD_VALUERING_H
25 
26 #include <QList>
27 #include <QPair>
28 
29 #include <chrono>
30 
31 #define VALUERING_DEBUG 0
32 
33 #if VALUERING_DEBUG
34 #include <QDebug>
35 #endif
36 
37 namespace QtPdCom {
38 
39 /****************************************************************************/
40 
43 template <class T> class ValueRing
44 {
45  public:
46  ValueRing();
47  ~ValueRing();
48 
49  void setRange(std::chrono::nanoseconds);
50  std::chrono::nanoseconds getRange() const { return range; }
51 
52  void append(std::chrono::nanoseconds time, const T &value);
53  void copyUntil(const ValueRing<T> &, std::chrono::nanoseconds);
54  void clear();
55 
56  unsigned int getLength() const;
57 
58  typedef QPair<std::chrono::nanoseconds, T> TimeValuePair;
59  TimeValuePair &operator[](unsigned int index);
60  const TimeValuePair &operator[](unsigned int index) const;
61  TimeValuePair &operator[](int index);
62  const TimeValuePair &operator[](int index) const;
63 
64  private:
65  QList<TimeValuePair> ring;
66  unsigned int offset;
67  unsigned int length;
68  std::chrono::nanoseconds range;
72  void removeDeprecated();
73  void reshape();
74 };
75 
76 /****************************************************************************/
77 
80 template <class T> ValueRing<T>::ValueRing():
81  offset(0),
82  length(0)
83 {}
84 
85 /****************************************************************************/
86 
89 template <class T> ValueRing<T>::~ValueRing()
90 {}
91 
92 /****************************************************************************/
93 
96 template <class T> void ValueRing<T>::setRange(std::chrono::nanoseconds r)
97 {
98  range = r;
99  removeDeprecated();
100 }
101 
102 /****************************************************************************/
103 
106 template <class T>
107 void ValueRing<T>::append(std::chrono::nanoseconds time, const T &value)
108 {
109  TimeValuePair newPair(time, value);
110 
111  if ((int) length < ring.size()) {
112  unsigned int o = (offset + length) % ring.size();
113  ring[o] = newPair;
114  }
115  else {
116 #if VALUERING_DEBUG
117  qDebug() << ring.size() << "reached.";
118 #endif
119  // ring is full
120  if (offset) {
121  reshape();
122  }
123  ring.append(newPair);
124  }
125 
126  length++;
127  removeDeprecated();
128 }
129 
130 /****************************************************************************/
131 
134 template <class T> void ValueRing<T>::copyUntil(
135  const ValueRing<T> &other,
136  std::chrono::nanoseconds time)
137 {
138  clear();
139 
140  for (unsigned int i = 0; i < other.length; i++) {
141  TimeValuePair p = other[i];
142  if (p.first > time) {
143  break;
144  }
145 
146  ring.append(p);
147  length++;
148  }
149 }
150 
151 /****************************************************************************/
152 
155 template <class T> void ValueRing<T>::clear()
156 {
157  ring.clear();
158  offset = 0;
159  length = 0;
160 }
161 
162 /****************************************************************************/
163 
167 template <class T> inline unsigned int ValueRing<T>::getLength() const
168 {
169  return length;
170 }
171 
172 /****************************************************************************/
173 
176 template <class T> inline typename ValueRing<T>::TimeValuePair &
177 ValueRing<T>::operator[](unsigned int index)
178 {
179  return ring[(offset + index) % ring.size()];
180 }
181 
182 /****************************************************************************/
183 
186 template <class T> inline const typename ValueRing<T>::TimeValuePair &
187 ValueRing<T>::operator[](unsigned int index) const
188 {
189  return ring.at((offset + index) % ring.size());
190 }
191 
192 /****************************************************************************/
193 
198 template <class T> inline typename ValueRing<T>::TimeValuePair &
200 {
201  if (index >= 0) {
202  return ring[(offset + index) % ring.size()];
203  }
204  else {
205  return ring[(offset + length + index) % ring.size()];
206  }
207 }
208 
209 /****************************************************************************/
210 
215 template <class T> inline const typename ValueRing<T>::TimeValuePair &
216 ValueRing<T>::operator[](int index) const
217 {
218  if (index >= 0) {
219  return ring.at((offset + index) % ring.size());
220  }
221  else {
222  return ring.at((offset + length + index) % ring.size());
223  }
224 }
225 
226 /****************************************************************************/
227 
230 template <class T> void ValueRing<T>::removeDeprecated()
231 {
232  if (length) {
233  std::chrono::nanoseconds depTime((*this)[length - 1].first - range);
234  while (length) {
235  if (ring[offset].first < depTime) {
236  offset = (offset + 1) % ring.size();
237  length--;
238  }
239  else {
240  break;
241  }
242  }
243  }
244 }
245 
246 /****************************************************************************/
247 
250 template <class T> void ValueRing<T>::reshape()
251 {
252  QList<TimeValuePair> newRing;
253  unsigned int i;
254 
255 #if VALUERING_DEBUG
256  qDebug() << "reshaping" << length << "values";
257 #endif
258 
259  for (i = 0; i < length; i++) {
260  newRing.append((*this)[i]);
261  }
262  ring = newRing;
263  offset = 0;
264 }
265 
266 /****************************************************************************/
267 
268 } // namespace QtPdCom
269 
270 #endif
Time/Value ring buffer.
Definition: ValueRing.h:43
TimeValuePair & operator[](unsigned int index)
Index operator.
Definition: ValueRing.h:177
ValueRing()
Constructor.
Definition: ValueRing.h:80
void removeDeprecated()
Remove values that exceed the time range.
Definition: ValueRing.h:230
unsigned int offset
Ring offset.
Definition: ValueRing.h:66
std::chrono::nanoseconds range
Time range covered by the ring.
Definition: ValueRing.h:68
Definition: BroadcastModel.h:32
void copyUntil(const ValueRing< T > &, std::chrono::nanoseconds)
Copies data from another ring, up to a specific time.
Definition: ValueRing.h:134
std::chrono::nanoseconds getRange() const
Definition: ValueRing.h:50
void setRange(std::chrono::nanoseconds)
Sets the range.
Definition: ValueRing.h:96
QPair< std::chrono::nanoseconds, T > TimeValuePair
Definition: ValueRing.h:58
~ValueRing()
Destructor.
Definition: ValueRing.h:89
unsigned int getLength() const
Definition: ValueRing.h:167
QList< TimeValuePair > ring
Time/Value ring.
Definition: ValueRing.h:65
unsigned int length
Number of valid elements at offset.
Definition: ValueRing.h:67
void reshape()
Reshape the ring to move the offset to zero.
Definition: ValueRing.h:250
void clear()
Clears the ring.
Definition: ValueRing.h:155
void append(std::chrono::nanoseconds time, const T &value)
Appends a value to the ring.
Definition: ValueRing.h:107