Skip to content

Instantly share code, notes, and snippets.

@csm
Last active September 14, 2017 19:29
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save csm/1d2d708029a79db937c01b7d1c01dc30 to your computer and use it in GitHub Desktop.
Save csm/1d2d708029a79db937c01b7d1c01dc30 to your computer and use it in GitHub Desktop.
(import '[io.netty.util Recycler])
(defprotocol Recyclable
(recycle! [this] "Recycles this object."))
(defprotocol Init
(init! [this values]))
(defmacro defrecyclable
[name fields & {:keys [max-capacity] :or {max-capacity 8096}}]
{:pre [(vector? fields)]}
(let [recycler-sym (gensym (str name "-recycler-"))]
`(do
(declare ^:private ~(symbol (str "mk-" name)))
(def ^:private ~recycler-sym
(proxy [Recycler] [~max-capacity]
(newObject [h#]
(~(symbol (str "mk-" name)) h#))))
(deftype ~name [~@fields handle# in-use#]
ILookup
(valAt [_# k# nf#]
(if (deref in-use#)
(let [m# ~(into {} (map (fn valAt-lookup [n] [(keyword n) `(fn [] (deref ~n))]) fields))
f# (get m# k# (constantly nf#))]
(f#))
(throw (IllegalStateException. "recycled object"))))
(valAt [t# k#]
(.valAt t# k# nil))
Associative
(containsKey [_# k#]
(if (deref in-use#)
(some? (#{~@(map keyword fields)} k#))
(throw (IllegalStateException. "recycled object"))))
(entryAt [t# k#]
(if (deref in-use#)
(when-let [v# (get t# k#)]
(AbstractMap$SimpleImmutableEntry k# v#))
(throw (IllegalStateException. "recycled object"))))
(assoc [_# k# v#]
(if (deref in-use#)
(let [m# (hash-map ~@(mapcat (fn [f] `[~(keyword f) (deref ~f)]) fields))]
(assoc m# k# v#))
(throw (IllegalStateException. "recycled object"))))
Seqable
(seq [t#]
(if (deref in-use#)
(seq [~@(map (fn [f] `[~(keyword f) (deref ~f)]) fields)])
(throw (IllegalStateException. "recycled object"))))
Counted
(count [_#]
~(count fields))
IPersistentCollection
(cons [t# v#]
(let [[k# v#] v#]
(assoc t# k# v#)))
(equiv [t# o#]
(if (deref in-use#)
(or (identical? t# o#)
(= (seq t#) (seq o#)))
(throw (IllegalStateException. "recycled object"))))
Init
(init! [_# values#]
(let [[~@(map (fn quote-value [n] (symbol (str "in_" n))) fields)] values#]
(dosync
(if (false? (deref in-use#))
(do
(ref-set in-use# true)
~@(map (fn emit-set-value [n] `(ref-set ~n ~(symbol (str "in_" n)))) fields))
(throw (IllegalStateException. "object is in use"))))))
Recyclable
(recycle! [this#]
(dosync
(when (true? (deref in-use#))
(ref-set in-use# false)
(.recycle ~recycler-sym this# handle#)))))
(defn- ~(symbol (str "mk-" name))
[handle#]
(~(symbol (str name \.)) ~@(repeat (count fields) `(ref nil)) handle# (ref false)))
(defn ~(symbol (str '-> name)) [~@fields]
(let [v# (.get ~recycler-sym)]
(init! v# [~@fields])
v#)))))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment