/
CircularObjectBuffer.cs
94 lines (84 loc) · 2.91 KB
/
CircularObjectBuffer.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
/******************************************************************************
* Copyright (C) Leap Motion, Inc. 2011-2018. *
* Leap Motion proprietary and confidential. *
* *
* Use subject to the terms of the Leap Motion SDK Agreement available at *
* https://developer.leapmotion.com/sdk_agreement, or another agreement *
* between Leap Motion 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<T> 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;
}
}
}
}