File: ring-buffers.lisp

package info (click to toggle)
cl-containers 20140211-1
  • links: PTS, VCS
  • area: main
  • in suites: jessie, jessie-kfreebsd
  • size: 1,076 kB
  • ctags: 1,386
  • sloc: lisp: 8,330; makefile: 14
file content (116 lines) | stat: -rw-r--r-- 3,328 bytes parent folder | download | duplicates (4)
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
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
(in-package #:containers)

;;; Ring Buffers
;;;
;;; Code adapted from ANSI Common Lisp by Paul Graham (chapter 7)
;;;
;;; A ring buffer is a bounded queue. It supports:
;;;   item-at (setf item-at)
;;;   insert-item, dequeue, empty!, empty-p, size, total-size, first-element

(defclass* ring-buffer (abstract-queue
                          bounded-container-mixin
                          iteratable-container-mixin
                          concrete-container)
  ((contents :initarg :contents
             :reader contents)
   (buffer-start :initform 0
                 :reader buffer-start)
   (buffer-end :initform 0
               :reader buffer-end)
   (total-size :initarg :total-size
               :reader total-size)))

(defun make-ring-buffer (size)
  (make-instance 'ring-buffer
    :contents (make-array size)
    :total-size size))

(defmethod make-container ((class (eql 'ring-buffer)) &rest args)
   (let ((total-size (getf args :total-size 1)))
     (remf args :total-size)
     (make-ring-buffer total-size)))


;;?? the (first indexes) is odd...
(defmethod item-at ((container ring-buffer) &rest indexes)
   (declare (dynamic-extent indexes))
   (svref (contents container)
          (mod (first indexes) (total-size container))))

(defmethod item-at! ((container ring-buffer) value &rest indexes)
  (declare (dynamic-extent indexes))
  (setf (svref (contents container)
                (mod (first indexes) (total-size container)))
         value))


(defmethod increment-end ((container ring-buffer))
   (with-slots (buffer-end buffer-start) container
     (when (and (>= buffer-end (total-size container))
                (= (mod buffer-end (total-size container)) buffer-start))
       (incf buffer-start))
     (incf buffer-end)))


(defmethod next-item ((container ring-buffer))
  (increment-end container)
  (current-item container))


(defmethod current-item ((container ring-buffer))
  (item-at container (buffer-end container)))


(defmethod insert-item ((container ring-buffer) item)
   (prog1
     (setf (item-at container (buffer-end container)) item)
     (increment-end container)))


(defmethod delete-first ((container ring-buffer))
   (with-slots (buffer-start) container
     (prog1
       (item-at container buffer-start)
       (incf buffer-start))))


(defmethod empty! ((container ring-buffer))
   (with-slots (buffer-end buffer-start)
               container
     (setf buffer-start 0
           buffer-end 0))

   (values))


#+Ignore
(defmethod total-size ((container ring-buffer))
   (total-size container))


(defmethod size ((container ring-buffer))
   (- (buffer-end container) (buffer-start container)))


(defmethod first-element ((container ring-buffer))
   (item-at container (buffer-start container)))


(defmethod (setf first-element) (value (container ring-buffer))
   (setf (item-at container (buffer-start container)) value))


(defmethod iterate-nodes ((container ring-buffer) fn)
   (loop for index from (buffer-start container) to (1- (buffer-end container)) do
         (funcall fn (item-at container index))))

#+No
;; screws with the buffer pointers
(defmethod iterate-nodes ((container ring-buffer) fn)
  (loop repeat (total-size container)
        with item = (current-item container) do
        (funcall fn item)
        (setf item (next-item container))))