Last active
September 14, 2017 19:29
-
-
Save csm/1d2d708029a79db937c01b7d1c01dc30 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
(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