--- a/make-docs.lisp Thu Apr 08 20:29:51 2021 -0400
+++ b/make-docs.lisp Thu Apr 08 20:30:18 2021 -0400
@@ -22,6 +22,7 @@
"LOSH.PRIORITY-QUEUES"
"LOSH.QUEUES"
"LOSH.RANDOM"
+ "LOSH.RING-BUFFERS"
"LOSH.SEQUENCES"
"LOSH.SHELL"
"LOSH.WEIGHTLISTS"
--- a/package.lisp Thu Apr 08 20:29:51 2021 -0400
+++ b/package.lisp Thu Apr 08 20:30:18 2021 -0400
@@ -178,6 +178,29 @@
:pq-ensure
:pq-dequeue))
+(defpackage :losh.ring-buffers
+ (:use :cl :iterate :losh.quickutils
+ :losh.chili-dogs
+ :losh.eldritch-horrors
+ :losh.mutation)
+ (:documentation "Simple ring buffer implementation.")
+ (:export
+
+ :do-ring-buffer
+ :make-ring-buffer
+ :rb-contents
+ :rb-count
+ :rb-empty-p
+ :rb-full-p
+ :rb-pop
+ :rb-push
+ :rb-ref
+ :rb-safe-push
+ :rb-size
+ :ring-buffer
+
+ ))
+
(defpackage :losh.control-flow
(:use :cl :iterate :losh.quickutils
@@ -256,17 +279,20 @@
(defpackage :losh.iterate
(:use :cl :iterate :losh.quickutils
- :losh.hash-sets)
+ :losh.hash-sets
+ :losh.ring-buffers)
(:documentation "Custom `iterate` drivers and clauses.")
(:export
:across-flat-array
+ :against
:anding
:averaging
:collect-frequencies
:collect-hash
:collect-set
:cycling
+ :end
:every-nth
:finding-all
:finding-first
@@ -274,31 +300,30 @@
:in-array
:in-hashset
:in-lists
+ :in-ring-buffer
:in-sequences
:in-whatever
:index-of-flat-array
:initially
:into
:macroexpand-iterate
+ :matching
:modulo
:oring
+ :overlap
:pairs-of-list
:per-iteration-into
:real-time
+ :returning
:run-time
:seed
:since-start-into
:skip-origin
+ :start
:test
:then
:timing
:within-radius
- :returning
- :matching
- :against
- :overlap
- :start
- :end
))
@@ -419,6 +444,7 @@
:losh.priority-queues
:losh.queues
:losh.random
+ :losh.ring-buffers
:losh.sequences
:losh.shell
:losh.weightlists
--- a/src/iterate.lisp Thu Apr 08 20:29:51 2021 -0400
+++ b/src/iterate.lisp Thu Apr 08 20:30:18 2021 -0400
@@ -730,6 +730,24 @@
`(,kwd (,var) :in-hashtable (losh.hash-sets::hash-set-storage ,hset))))
+(defmacro-driver (FOR var IN-RING-BUFFER ring-buffer)
+ "Iterate over the elements of `ring-buffer`, oldest to newest."
+ (let ((kwd (if generate 'generate 'for)))
+ (with-gensyms (rb r w d s)
+ `(progn
+ (with ,rb = ,ring-buffer)
+ (with ,r = (losh.ring-buffers::r ,rb))
+ (with ,w = (losh.ring-buffers::w ,rb))
+ (with ,d = (losh.ring-buffers::data ,rb))
+ (with ,s = (losh.ring-buffers::size ,rb))
+ (,kwd ,var :next (if (= ,r ,w)
+ (terminate)
+ (prog1 (svref ,d ,r)
+ (incf ,r)
+ (when (= ,r ,s)
+ (setf ,r 0)))))))))
+
+
(defmacro-driver (FOR var SEED seed THEN then)
"Bind `var` to `seed` initially, then to `then` on every iteration.