initial commit
This commit is contained in:
Executable
+131
@@ -0,0 +1,131 @@
|
||||
;; Copyright (c) Rich Hickey and contributors. All rights reserved.
|
||||
;; The use and distribution terms for this software are covered by the
|
||||
;; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php)
|
||||
;; which can be found in the file epl-v10.html at the root of this distribution.
|
||||
;; By using this software in any fashion, you are agreeing to be bound by
|
||||
;; the terms of this license.
|
||||
;; You must not remove this notice, or any other, from this software.
|
||||
|
||||
(ns cljs.core.async.impl.buffers
|
||||
(:require [cljs.core.async.impl.protocols :as impl]))
|
||||
|
||||
;; -----------------------------------------------------------------------------
|
||||
;; DO NOT USE, this is internal buffer representation
|
||||
|
||||
(defn acopy [src src-start dest dest-start len]
|
||||
(loop [cnt 0]
|
||||
(when (< cnt len)
|
||||
(aset dest
|
||||
(+ dest-start cnt)
|
||||
(aget src (+ src-start cnt)))
|
||||
(recur (inc cnt)))))
|
||||
|
||||
(deftype RingBuffer [^:mutable head ^:mutable tail ^:mutable length ^:mutable arr]
|
||||
Object
|
||||
(pop [_]
|
||||
(when-not (zero? length)
|
||||
(let [x (aget arr tail)]
|
||||
(aset arr tail nil)
|
||||
(set! tail (js-mod (inc tail) (alength arr)))
|
||||
(set! length (dec length))
|
||||
x)))
|
||||
|
||||
(unshift [_ x]
|
||||
(aset arr head x)
|
||||
(set! head (js-mod (inc head) (alength arr)))
|
||||
(set! length (inc length))
|
||||
nil)
|
||||
|
||||
(unbounded-unshift [this x]
|
||||
(if (== (inc length) (alength arr))
|
||||
(.resize this))
|
||||
(.unshift this x))
|
||||
|
||||
;; Doubles the size of the buffer while retaining all the existing values
|
||||
(resize
|
||||
[_]
|
||||
(let [new-arr-size (* (alength arr) 2)
|
||||
new-arr (make-array new-arr-size)]
|
||||
(cond
|
||||
(< tail head)
|
||||
(do (acopy arr tail new-arr 0 length)
|
||||
(set! tail 0)
|
||||
(set! head length)
|
||||
(set! arr new-arr))
|
||||
|
||||
(> tail head)
|
||||
(do (acopy arr tail new-arr 0 (- (alength arr) tail))
|
||||
(acopy arr 0 new-arr (- (alength arr) tail) head)
|
||||
(set! tail 0)
|
||||
(set! head length)
|
||||
(set! arr new-arr))
|
||||
|
||||
(== tail head)
|
||||
(do (set! tail 0)
|
||||
(set! head 0)
|
||||
(set! arr new-arr)))))
|
||||
|
||||
(cleanup [this keep?]
|
||||
(dotimes [x length]
|
||||
(let [v (.pop this)]
|
||||
(when ^boolean (keep? v)
|
||||
(.unshift this v))))))
|
||||
|
||||
(defn ring-buffer [n]
|
||||
(assert (> n 0) "Can't create a ring buffer of size 0")
|
||||
(RingBuffer. 0 0 0 (make-array n)))
|
||||
|
||||
;; -----------------------------------------------------------------------------
|
||||
|
||||
(deftype FixedBuffer [buf n]
|
||||
impl/Buffer
|
||||
(full? [this]
|
||||
(== (.-length buf) n))
|
||||
(remove! [this]
|
||||
(.pop buf))
|
||||
(add!* [this itm]
|
||||
(.unbounded-unshift buf itm)
|
||||
this)
|
||||
cljs.core/ICounted
|
||||
(-count [this]
|
||||
(.-length buf)))
|
||||
|
||||
(defn fixed-buffer [n]
|
||||
(FixedBuffer. (ring-buffer n) n))
|
||||
|
||||
(deftype DroppingBuffer [buf n]
|
||||
impl/UnblockingBuffer
|
||||
impl/Buffer
|
||||
(full? [this]
|
||||
false)
|
||||
(remove! [this]
|
||||
(.pop buf))
|
||||
(add!* [this itm]
|
||||
(when-not (== (.-length buf) n)
|
||||
(.unshift buf itm))
|
||||
this)
|
||||
cljs.core/ICounted
|
||||
(-count [this]
|
||||
(.-length buf)))
|
||||
|
||||
(defn dropping-buffer [n]
|
||||
(DroppingBuffer. (ring-buffer n) n))
|
||||
|
||||
(deftype SlidingBuffer [buf n]
|
||||
impl/UnblockingBuffer
|
||||
impl/Buffer
|
||||
(full? [this]
|
||||
false)
|
||||
(remove! [this]
|
||||
(.pop buf))
|
||||
(add!* [this itm]
|
||||
(when (== (.-length buf) n)
|
||||
(impl/remove! this))
|
||||
(.unshift buf itm)
|
||||
this)
|
||||
cljs.core/ICounted
|
||||
(-count [this]
|
||||
(.-length buf)))
|
||||
|
||||
(defn sliding-buffer [n]
|
||||
(SlidingBuffer. (ring-buffer n) n))
|
||||
Reference in New Issue
Block a user