geopm  3.1.1.dev272+gdfb40a8d
GEOPM - Global Extensible Open Power Manager
CircularBuffer.hpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2015 - 2024 Intel Corporation
3  * SPDX-License-Identifier: BSD-3-Clause
4  */
5 
6 #ifndef CIRCULARBUFFER_HPP_INCLUDE
7 #define CIRCULARBUFFER_HPP_INCLUDE
8 
9 #include <stdlib.h>
10 
11 #include <vector>
12 
13 #include "geopm_public.h"
14 
15 #include "Exception.hpp"
16 
17 namespace geopm
18 {
22  template <class type>
24  {
25  public:
32  CircularBuffer(unsigned int size);
34  virtual ~CircularBuffer();
44  void set_capacity(const unsigned int size);
48  void clear(void);
54  //
56  int size(void) const;
63  int capacity(void) const;
73  void insert(const type value);
92  const type& value(const int index) const;
96  std::vector<type> make_vector(void) const;
106  std::vector<type> make_vector(const unsigned int start, const unsigned int end) const;
107  private:
109  std::vector<type> m_buffer;
111  unsigned long m_head;
113  unsigned long m_count;
115  size_t m_max_size;
116  };
117 
118  template <class type>
120  : CircularBuffer(0)
121  {
122 
123  }
124 
125  template <class type>
127  : m_buffer(size)
128  , m_head(0)
129  , m_count(0)
130  , m_max_size(size)
131  {
132 
133  }
134 
135  template <class type>
137  {
138 
139  }
140 
141  template <class type>
143  {
144  return m_count;
145  }
146 
147  template <class type>
149  {
150  return m_max_size;
151  }
152 
153  template <class type>
155  {
156  m_head = 0;
157  m_count = 0;
158  }
159 
160  template <class type>
161  void CircularBuffer<type>::set_capacity(const unsigned int size)
162  {
163  // If the requested new capacity is less than the size.
164  if (size < m_count && m_max_size > 0) {
165  int size_diff = m_count - size;
166  std::vector<type> temp;
167  for (size_t idx = size_diff; idx < m_count; ++idx) {
168  temp.push_back(value(idx));
169  }
170  //now re-size and swap out with tmp vector data
171  m_buffer.resize(size);
172  m_buffer.swap(temp);
173  m_count = size;
174  }
175  else {
176  m_buffer.resize(size);
177  }
178  m_head = 0;
179  m_max_size = size;
180  }
181 
182  template <class type>
183  void CircularBuffer<type>::insert(const type value)
184  {
185  if (m_max_size < 1) {
186  throw Exception("CircularBuffer::insert(): Cannot insert into a buffer of 0 size", GEOPM_ERROR_RUNTIME, __FILE__, __LINE__);
187  }
188  if (m_count < m_max_size) {
189  m_buffer.at(m_count) = value;
190  m_count++;
191  }
192  else {
193  m_buffer.at(m_head) = value;
194  m_head = ((m_head + 1) % m_max_size);
195  }
196  }
197 
198  template <class type>
199  const type& CircularBuffer<type>::value(const int index) const
200  {
201  if (index >= static_cast<int>(m_count) || index < -static_cast<int>(m_count)) {
202  throw Exception(std::string("CircularBuffer::value(): index [") + std::to_string(index) + "] is out of bounds",
203  GEOPM_ERROR_INVALID, __FILE__, __LINE__);
204  }
205  if (index < 0) {
206  const int new_index = m_count + index;
207  return m_buffer.at((m_head + new_index) % m_max_size);
208  } else {
209  return m_buffer.at((m_head + index) % m_max_size);
210  }
211  }
212 
213  template <class type>
214  std::vector<type> CircularBuffer<type>::make_vector(void) const
215  {
216  std::vector<type> result(size());
217  if (m_head == 0) {
218  std::copy(m_buffer.begin(), m_buffer.begin() + m_count, result.begin());
219  }
220  else {
221  std::copy(m_buffer.begin() + m_head, m_buffer.end(), result.begin());
222  std::copy(m_buffer.begin(), m_buffer.begin() + m_head, result.end() - m_head);
223  }
224  return result;
225  }
226 
227  template <class type>
228  std::vector<type> CircularBuffer<type>::make_vector(const unsigned int idx_start, const unsigned int idx_end) const
229  {
230  if (idx_start >= (unsigned int)size()) {
231  throw Exception("CircularBuffer::make_vector(): start is out of bounds", GEOPM_ERROR_INVALID, __FILE__, __LINE__);
232  }
233  if (idx_end > (unsigned int)size()) {
234  throw Exception("CircularBuffer::make_vector(): end is out of bounds", GEOPM_ERROR_INVALID, __FILE__, __LINE__);
235  }
236  if (idx_end <= idx_start) {
237  throw Exception("CircularBuffer::make_vector(): end index is smaller than start index", GEOPM_ERROR_INVALID, __FILE__, __LINE__);
238  }
239 
240  int slice_length = idx_end - idx_start;
241  std::vector<type> result(slice_length);
242 
243  unsigned int start=(m_head + idx_start) % capacity();
244  unsigned int end=(((m_head + idx_end) - 1) % capacity()) + 1;
245 
246  if(end > start) {
247  std::copy(m_buffer.begin() + start, m_buffer.begin() + end, result.begin());
248  }
249  else {
250  std::copy(m_buffer.begin() + start, m_buffer.end(), result.begin());
251  std::copy(m_buffer.begin(), m_buffer.begin() + end, result.begin() + capacity() - start);
252  }
253  return result;
254  }
255 
256 }
257 
258 #endif
Templated container for a circular buffer implementation. The CircularBuffer container implements a f...
Definition: CircularBuffer.hpp:24
virtual ~CircularBuffer()
CircularBuffer destructor, virtual.
Definition: CircularBuffer.hpp:136
std::vector< type > make_vector(void) const
Create a vector from the entire circular buffer contents.
Definition: CircularBuffer.hpp:214
int capacity(void) const
Capacity of the buffer.
Definition: CircularBuffer.hpp:148
int size(void) const
Size of the buffer contents.
Definition: CircularBuffer.hpp:142
const type & value(const int index) const
Returns a constant reference to the value from the buffer.
Definition: CircularBuffer.hpp:199
void clear(void)
Clears all entries from the buffer.
Definition: CircularBuffer.hpp:154
CircularBuffer()
Definition: CircularBuffer.hpp:119
void set_capacity(const unsigned int size)
Re-size the circular buffer.
Definition: CircularBuffer.hpp:161
std::vector< type > make_vector(const unsigned int start, const unsigned int end) const
Create a vector slice from the circular buffer contents.
Definition: CircularBuffer.hpp:228
void insert(const type value)
Insert a value into the buffer.
Definition: CircularBuffer.hpp:183
CircularBuffer(unsigned int size)
Constructor for the CircularBuffer template.
Definition: CircularBuffer.hpp:126
Class for all GEOPM-specific exceptions.
Definition: Exception.hpp:48
@ GEOPM_ERROR_INVALID
Definition: geopm_error.h:20
@ GEOPM_ERROR_RUNTIME
Definition: geopm_error.h:18
Definition: Agg.cpp:20