Featuring::
* CircularBuffer
-* LogBuffer (saves one of the 2 last items, one of the 4 last items, ..
- of the 8 last, 16 last, ...
+* LogarithmicBuffer: saves only last N items, and after that less and less so
+* very few old items are kept
.. codeauthor:: Christian Herdtweck, christian.herdtweck@intra2net.com
"""
result.append(self._buffer[idx])
return result
+
+
+class LogarithmicBuffer:
+ """ saves only last N items, and after that less and less; old stuff is del
+
+ --> grows only logarithmically in size
+
+ has a data_new which is a CircularBuffer for the last N items
+ data_old is a list of items with ages approx 2, 4, 8, 16, ... counts
+
+ Could easily extend to other bases than 2 to make even scarcer
+ """
+
+ def __init__(self, n_new):
+ self.n_new = n_new
+ if n_new < 0:
+ raise ValueError('n_new must be non-negative!')
+ if n_new == 0:
+ self.data_new = None
+ else:
+ self.data_new = CircularBuffer(n_new)
+ self.count = 0
+ self.data_old = []
+
+ def add(self, new_item):
+ """ add a new item to buffer """
+ if self.data_new:
+ newest_old_item = data_new.add(new_item)
+ age = count - n_new
+ else:
+ newest_old_item = new_item
+ age = count
+
+ _save_old(newest_old_item, age, 0)
+ self.count += 1
+
+ def _save_old(item, age, index):
+ """ internal helper for saving (or not) items in data_old """
+
+ # determine whether we throw it away or actually save it
+ if age % 2**index != 0:
+ return
+
+ # we will save it. But before overwriting the item that was there,
+ # we determine whether that will be saved at next index
+ _save_old(data_old[index], age, index+1)
+
+ # now do save at index, possibly extending data_old
+ if len(data_old) < index:
+ data_old.append(item)
+ else:
+ data_old[index] = item
+
+ def get_all(self):
+ """ get all buffer contents in correct order """
+ if self.data_new:
+ return self.data_old[::-1] + self.data_new.get_all()
+ else:
+ return self.data_old[::-1]