Created
November 4, 2020 22:16
-
-
Save matthewdowney/8adcff7ee58891ff17f16066e3ab6b1e to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(ns user.ring-buffer | |
"A fast, mutable ring buffer, backed by a fixed Java array. | |
Prefer https://github.com/clj-commons/ring-buffer unless you have very | |
specific needs." | |
(:require [taoensso.tufte :as tufte]) | |
(:import (clojure.lang IDeref))) | |
(defprotocol ^:private Cursor (get-cursor! [this])) | |
(deftype ^:private RingBuffer [^:unsynchronized-mutable cursor size buf] | |
IDeref (deref [this] (vec buf)) | |
Cursor (get-cursor! [this] (set! cursor (inc cursor)))) | |
(defn ring-buffer | |
"Create a ring buffer of the given size. | |
Supports `deref` and `rb-conj!`." | |
[size] | |
(RingBuffer. -1 size (make-array Object size))) | |
(defn rb-conj! | |
"N.B. NOT thread safe. | |
Insert element `x` into the ring buffer `rb`. | |
Returns the element that `x` displaced, otherwise nil." | |
[^RingBuffer rb x] | |
(tufte/p :rb/insert | |
(let [cursor (get-cursor! rb) | |
index (rem cursor (.size rb)) | |
^objects buf (.buf rb) | |
prev (aget buf index)] | |
(aset buf index ^Object x) | |
prev))) | |
(comment | |
(def b (ring-buffer 30)) | |
(tufte/add-basic-println-handler! {}) | |
(tufte/profile {} (dotimes [i 5e6] (rb-conj! b i))) | |
; Mean of 65 ns for insertion | |
) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment