Is it possible to deinitialize the class without calling the gc?
Adam D. Ruppe
destructionator at gmail.com
Fri Aug 3 21:44:55 UTC 2018
On Friday, 3 August 2018 at 20:40:31 UTC, 12345swordy wrote:
> Did you even bother reading the links that I posted?
I did. Did you? The wikipedia page speaks at length to the
ambiguity of the terms, including that the language construct can
be called a destructor while the implementation methods can be
called a finalizer, even if they do the same thing.
> Then you should know where the implementation of finalize is
> located at, or am I looking at the wrong code here?
It is in rt/lifetime.d.
The .destroy(class) function is defined on line 560 of object.d
in druntime/src (assuming code as of v2.081.1 release). This
calls rt_finalize, defined on line 1422 of rt/lifetime.d (and
note that there is a separate function right under it for
finalizeFromGC!).
This simply forwards to rt_finalize2, defined on line 1380 in the
same file, which does the actual work. Observe how it simply
calls the destructors, in order, of the base class instances,
then deletes the monitor if it is present, and copies the
initialize memory over to make that predictable, but then nulls
out pointer to the rtti instance for that dead object, to ensure
it is unusable.
The one you linked to is totally unrelated. It doesn't even
define a function called destroy nor rt_finalize. It actually
defines a function to finalize the (manual) GC object itself!
Its run finalizers method is supposed to detect what type of
objects are in the passed memory block, and call rt_finalize (or
one of its variants) for them. But, of course, since it is just a
stub implementation of the GC interface, it doesn't actually do
that.
rt_finalize is called BY the GC or the public destroy function,
but it is NOT part of the GC. It also does not call into any GC
functions itself (though user-defined hooks or class destructors
might - but note if a class dtor does, it is liable to cause the
program to terminate with InvalidMemoryOperatorError in certain
circumstances).
It is also called by the language almost directly in the case of
`scope` classes, via the `_d_callfinalizer` function (defined on
line 1238 of rt/lifetime.d, where you can see it is a simple
forward to rt_finalize). scope classes are allocated and
destroyed just like structs - they live on the stack and their
destructors are called deterministically when they go out of
scope. Explicitly not GC'd... but still calling the same
rt_finalize function.
BTW: Generally speaking, the calls to _d_xxxx functions are
emitted by the compiler itself, then they forward to _rt_xxx
functions, which are the internal runtime implementations, and
those _rt_xxx functions are also accessible through other public
interfaces, like the .destroy() function, or Runtime.xxx static
struct methods, etc., to give them a prettier name. Those
prettier names are the documented ways to access it, whereas the
_rt_ ones are subject to change without notice by druntime devs
and the _d_ ones are subject to change by dmd devs.
So, again:
> Is it possible to deinitialize the class without calling the gc?
Yes, use the .destroy function, or a scope class (or the scoped!
template in std.typecons, which tried to replace the built-in
scope thing due to memory safety concerns at one point).
> Is there RecusiveDestruct function that can be called that is
> attribute friendly?
No. Best you have is the .destroy function, which cannot work
with the attributes because the D language definition does not
make that possible. Child classes have independent destructors
which do not need to adhere to the attributes of the parent class
destructor, and moreover this cannot be detected at compile time
when the attributes are processed - yet both must be called.
Thus, at compile time, the destruction process must assume the
widest possible features and the attributes do not apply.
More information about the Digitalmars-d
mailing list