In ResourcePools.jl/pooled_abstract_array.jl at feature/multi-threading · IHPSystems/ResourcePools.jl · GitHub, I have two concepts - in addition to pooled resources / pools of resources:
- Reference counted instances - that can be
retain!
'ed and release!
'ed - and where something should happen when the reference count reaches zero. Thread-safe.
- Disposables - instances that react to
dispose!
, e.g., by cleaning up memory allocated outside Julia.
I have yet to find these quite common concepts in Base. Are they there somewhere or should they be split out into separate tiny packages?
Related to Disposables: LLVM.jl defines a @dispose
macro “for disposing resources without do-block syntax”:
Helper macro for disposing resources (by calling the LLVM.dispose
function for every
resource in reverse order) after executing a block of code. This is often equivalent to
calling the recourse constructor with do-block syntax, but without using (potentially
costly) closures.
Introduced in Introduce at-dispose to replace do-block constructors. by maleadt · Pull Request #309 · maleadt/LLVM.jl · GitHub
@maleadt Care to comment on the prospect of “Disposables”? E.g. something outside LLVM that would do sort of the same thing…
I had something like the following (slightly bad idea) on my mind until looking at LLVM:
module Disposables
export dispose!, with_disposal
function dispose! end # dispose!(::T)
function with_disposal(f::Function, args...; kwargs...)
try
f(args...; kwargs...)
finally
for arg in args
dispose!(arg)
end
end
end
# test suite in a non-exported Testing sub-module for checking implementations of informal interface
# implementations of dispose!(::T) for Base types like arrays etc. ... - in a package extension or in a separate "DisposableBase" package
end # module
Issues:
dispose!
needs to consider interaction with GC - the same resource should not be disposed of twice in case someone hooks up dispose!
to GC finalization with finalizer
- similar to how IDisposable works in .NET (cf. IDisposable.Dispose(true)
vs IDisposable.Dispose(false)
)
dispose!
must be implemented in a thread-safe manner - without risking dead locks. E.g. in relation to thread-safe reference counting (with both “disposable” and “reference countable” having a lock…)
with_disposal
seems problematic: Should all arg in args
be disposed of? (probably not) Should they be disposed of in-order?
Something like the @dispose
macro is probably better than with_disposal
…