(ns com.snowtide.clojure.memoize) | |
(defn- mutable-memoize | |
[f #^java.util.Map map] | |
(fn [& args] | |
(if-let [e (find map args)] | |
(val e) | |
(let [ret (apply f args)] | |
(.put map args ret) | |
ret)))) | |
(defn soft-memoize | |
[f] | |
(let [m (java.util.concurrent.ConcurrentHashMap.) | |
rq (java.lang.ref.ReferenceQueue.) | |
memoized (mutable-memoize | |
#(java.lang.ref.SoftReference. (apply f %&) rq) | |
m)] | |
(fn clear-fn [& args] | |
; clearCache conveniently exists to poll the queue and scrub a CHM | |
; used in Clojure's Keyword and DynamicClassLoader, so it's not going anywhere | |
(clojure.lang.Util/clearCache rq m) | |
(let [^java.lang.ref.SoftReference ref (apply memoized args) | |
val (.get ref)] | |
(if (.isEnqueued ref) | |
; reference enqueued since our clearCache call above, retry | |
(apply clear-fn args) | |
val))))) | |
(defn weak-memoize | |
"Same as memoize, but uses a WeakHashMap for storing argument keys and result values. | |
**Be aware of what this entails for persistence of values: lose your keys, and | |
the associated value may get recalculated, depending upon the behaviour of the GC**" | |
[f] | |
(mutable-memoize f (java.util.WeakHashMap.))) | |
(defn lru-map | |
"Returns a least-recently-used cache implemented on top of LinkedHashMap | |
that uses eviction-fn to control cache eviction. | |
eviction-fn is a fn of two arguments (the LinkedHashMap cache and the | |
LRU map entry) that is called by the LHM when a new entry is added to | |
the cache. Returning a truthy value will result in the LRU entry being | |
evicted from the cache. (See LinkedHashMap.removeEldestEntry for more details.) | |
e.g. An LRU cache with a max size of 100 can be obtained via: | |
(lru-map (fn [m e] (> (count m) 100)))" | |
[eviction-fn] | |
(proxy [java.util.LinkedHashMap] [16 0.75 true] | |
(removeEldestEntry [entry] | |
(boolean (eviction-fn this entry))))) | |
(defn lru-memoize | |
"Same as memoize, but uses a LinkedHashMap-based LRU cache. | |
See `lru-map` for info about eviction-fn." | |
[f eviction-fn] | |
(mutable-memoize f (lru-map eviction-fn))) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment