Replies: 1 comment
-
|
I understand the idea. Given the other discussions going on about finalizers, I wonder again if the right solution is expose a few lower-level operations (which definitely belong in the It isn't clear to me why one would want signature CONTEXT_FINALIZABLE =
structure Context :
sig
type 'a t
val new: (('c -> unit) -> unit) -> 'c t
end
type ('a, 'c) t
val addFinalizer: ('a, 'c) t * ('a * 'c -> unit) -> unit
val finalizeBefore: ('a, 'ca) t * ('b, 'cb) t -> unit
val new: 'a * 'c Context.t -> ('a, 'c) t
val touch: ('a, 'c) t -> unit
val withValue: ('a, 'c) t * ('a -> 'b) -> 'band (uncontexted) finalizers would just be a specialization to a no-op context. And it seems that this could be implemented upon a lower-level set of operations that simply allowed the mutator to create different queues of pending finalizers. |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
-
Given many finalizers that use a common resource, there does not appear to be a way to run the finalizers as a group allowing the common resource to be used once. If use of the resource has an overhead, using the resource independently in each finalizer is inefficient. For example, the finalizers may need to obtain a common lock. In my case, the finalizers need to be scheduled in (a callback from) the application's main loop.
To provide general support for this I am using the following interface:
With this signature, a finalizable value is created in a context to allow its finalizers to be run with finalizers of other finalizable values created in the same context.
Context.new ().xin a contextcbynewInContext c x.mthat is registered usingContext.setMarshaler c (SOME m)will be used to run a group of finalizers of finalizable values in the contextcasynchronously following garbage collection.care not run asynchronously if no marshaler is set usingContext.setMarshaler. A marshalermis applied to a function that runs these finalizers usingContext.finalize c (m, doGC), wheredoGCis evaluated first, typically to perform garbage collection. The marshalermis run synchronously. (Whether these finalizers are run synchronously depends on the marshalerm.) Finalizers of finalizable values not in a context are also run synchronously. The result is false only if no finalizers were run betweendoGCreturning andContext.finalizereturning, i.e. without any other execution,falseindicates that evaluatingContext.finalize c (m, doGC)again would have no effect. UsingContext.finalize c (m1, doGC)when contextchas a marshaler set usingContext.setMarshaler c m2will result in one of the marshalersm1orm2being used but which marshaler is implementation-defined.Context.finalizemay be called where the argumentdoGCis the identity function in which case it performs synchronous finalization only.This interface therefore allows mixing of synchronous and asynchronous finalizers.
My case was more specific as I just needed a context for each thread. For this, I am using the following interface, whose implementation is derived from an implementation of
CONTEXT_FINALIZABLE:My MLton implementation assumes only one thread. Still, the distinction between
newandnewInThreadis useful because the latter is used for finalization of C objects that are not thread-safe (for which the marshaler adds the finalizers to a callback from the main application loop).Beta Was this translation helpful? Give feedback.
All reactions