Skip to content

Instantly share code, notes, and snippets.

@RutledgePaulV
Last active July 7, 2022 19:57
Show Gist options
  • Save RutledgePaulV/593a47e18160be2427ebdc8ef25d035a to your computer and use it in GitHub Desktop.
Save RutledgePaulV/593a47e18160be2427ebdc8ef25d035a to your computer and use it in GitHub Desktop.
self-cleaning-pool.clj
(defn gc-managed-pool
"Wraps a manually managed pool to create an automatically managed pool
that returns resources to the pool as the doled out references are
garbage collected by the jvm."
[pool borrow return]
(letfn [(interfaces [x]
(->> (ancestors (class x))
(filter class?)
(filter #(.isInterface %))))
(create-facade [x]
(Proxy/newProxyInstance
(.getClassLoader (class x))
(into-array Class (interfaces x))
(reify InvocationHandler
(invoke [this proxy method args]
(.invoke method x args)))))]
(let [queue (ReferenceQueue.)
references (atom #{})]
(future
(loop []
(when-some [ref (.remove queue)]
(let [{:keys [resource]} (meta ref)]
(try
(swap! references disj resource)
(return pool resource)
(finally (.clear ref)))
(recur)))))
(fn [& args]
(let [created (apply borrow pool args)
view (create-facade created)
state {:resource created}
reference (proxy [WeakReference IMeta] [view queue]
(meta [] state))]
(swap! references conj created)
view)))))
@RutledgePaulV
Copy link
Author

Wraps a manually managed resource pool with logic that returns resources to the pool as the doled out references are garbage collected by the JVM.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment