Skip to content

Instantly share code, notes, and snippets.

@rioki
Last active July 2, 2019 14:00
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rioki/5da93d5b398d8b1e2adbf525129e9655 to your computer and use it in GitHub Desktop.
Save rioki/5da93d5b398d8b1e2adbf525129e9655 to your computer and use it in GitHub Desktop.
// Copyright 2019 Sean Farrell <sean.farrell@rioki.org>
// This work is free. You can redistribute it and/or modify it under the
// terms of the Do What The Fuck You Want To Public License, Version 2,
// as published by Sam Hocevar. See http://www.wtfpl.net/ for more details.
#ifndef _ROUND_ROBIN_H_
#define _ROUND_ROBIN_H_
#include <array>
/*!
* A container of fixed size that cycles a given amount of items.
*/
template <typename Type, size_t COUNT>
class round_robin
{
public:
/*!
* Returns the number of elements
*
* @returns The number of elements in the container.
*/
size_t size() const
{
return COUNT;
}
/*!
* Access specified element
*
* Returns a reference to the element at specified location pos.
*
* @param pos position of the element to return
* @returns reference to the requested element
*
* @{
*/
Type& operator [] (ptrdiff_t pos)
{
auto i = static_cast<ptrdiff_t>(index) + (pos % static_cast<ptrdiff_t>(COUNT));
if (i < 0)
{
i += COUNT;
}
if (i >= COUNT)
{
i -= COUNT;
}
return values[i];
}
const Type& operator [] (ptrdiff_t pos) const
{
return const_cast<round_robin*>(this)->operator[](pos);
}
/*! @} */
/*!
* access specified element with bounds checking
*
* Returns a reference to the element at specified location pos, with bounds checking.
* If pos is not within the range of the container, an exception of type std::out_of_range is thrown.
*
* @param pos position of the element to return
* @returns reference to the requested element
* @throws std::out_of_range if `!(abs(pos) < size())`
*
* @{
*/
Type& at(ptrdiff_t pos)
{
auto i = static_cast<ptrdiff_t>(index) + (pos % static_cast<ptrdiff_t>(COUNT));
if (i < 0)
{
i += COUNT;
}
if (i >= COUNT)
{
i -= COUNT;
}
return values.at(i);
}
const Type& at(ptrdiff_t pos) const
{
return const_cast<round_robin*>(this)->at(pos);
}
/*! @} */
/*!
* Access a single item regardless of the current head value.
* @{
*/
Type& front()
{
return values[index];
}
const Type& front() const
{
return values[index];
}
/*! @} */
/*!
* Rotate the sequence one revolution
*/
void rotate()
{
index = (index + 1u) % COUNT;
}
private:
size_t index = 0;
std::array<Type, COUNT> values;
};
#endif
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment