/****************************************************************************** * Copyright (C) Ultraleap, Inc. 2011-2024. * * * * Use subject to the terms of the Apache License 2.0 available at * * http://www.apache.org/licenses/LICENSE-2.0, or another agreement * * between Ultraleap and you, your company or other organization. * ******************************************************************************/ namespace LeapInternal { //TODO add test for thread safety /** * A Limited capacity, circular LIFO buffer that wraps around * when full. Supports indexing to get older items. Array-backed. * * * Unlike many collections, objects are never removed, just overwritten when * the buffer cycles back to their array location. * * Object types used must have default parameterless constructor. It should be obvious that * such default objects are invalid. I.e. for Leap API objects, the IsValid property should be false. */ public class CircularObjectBuffer where T : new() { private T[] array; private int current = 0; private object locker = new object(); public int Count { get; private set; } public int Capacity { get; private set; } public bool IsEmpty { get; private set; } public CircularObjectBuffer(int capacity) { Capacity = capacity; array = new T[this.Capacity]; current = 0; Count = 0; IsEmpty = true; } /** Put an item at the head of the list. Once full, this will overwrite the oldest item. */ public virtual void Put(ref T item) { lock (locker) { if (!IsEmpty) { current++; if (current >= Capacity) { current = 0; } } if (Count < Capacity) Count++; lock (array) { array[current] = item; } IsEmpty = false; } } /** Get the item indexed backward from the head of the list */ public void Get(out T t, int index = 0) { lock (locker) { if (IsEmpty || (index > Count - 1) || index < 0) { t = new T(); //default(T); } else { int effectiveIndex = current - index; if (effectiveIndex < 0) { effectiveIndex += Capacity; } t = array[effectiveIndex]; } } } /** Increase */ public void Resize(int newCapacity) { lock (locker) { if (newCapacity <= Capacity) { return; } T[] newArray = new T[newCapacity]; int j = 0; for (int i = Count - 1; i >= 0; i--) { T t; Get(out t, i); newArray[j++] = t; } this.array = newArray; this.Capacity = newCapacity; } } } }