-
Notifications
You must be signed in to change notification settings - Fork 47
/
buffer.clj
72 lines (48 loc) · 1.44 KB
/
buffer.clj
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
(ns com.brunobonacci.mulog.buffer
(:require [amalloy.ring-buffer :as rb]))
(defprotocol PRingBuffer
"RingBuffer protocol"
(enqueue [this item]
"Add an item to the Ring Buffer.")
(dequeue [this offset]
"removes all the items in the ring buffer up to the and including the given offset")
(clear [this]
"removes all the items in the ring buffer")
(items [this]
"Returns a sequence of pairs [<offset> <item>]")
)
(defn- pop-while
"like drop-while but for amalloy/ring-buffer"
[pred buffer]
(if (some-> (peek buffer) pred)
(recur pred (pop buffer))
buffer))
(deftype RingBuffer [counter buffer]
;; This type uses amalloy/ring-buffer. Every item added has an
;; monotonically increasing offset in the form of pairs in a tuple
;; `[<offset> <item>]`. The offset can be used as high-water-mark
;; to dequeue processed items.
Object
(toString [this]
(pr-str buffer))
clojure.lang.Counted
(count [this]
(count buffer))
PRingBuffer
(enqueue [this item]
(let [id (inc counter)]
(RingBuffer. id (conj buffer [id item]))))
(dequeue [this offset]
(RingBuffer.
counter
(pop-while #(<= (first %) offset) buffer)))
(clear [this]
(RingBuffer. counter (empty buffer)))
(items [this]
buffer)
)
(defn ring-buffer
"Create an empty ring buffer with the specified [capacity]."
[capacity]
{:pre [(> capacity 0)]}
(RingBuffer. 0 (rb/ring-buffer capacity)))