- Method
destroy
void destroy(void|int reason)
- Description
Object destruction callback.
This function is called right before the object is destructed.
That can happen either through a call to destruct() ,
when there are no more references to the object, or when the
garbage collector discovers that it's part of a cyclic data
structure that has become garbage.
- Parameter reason
A flag that tells why the object is destructed:
Object.DESTRUCT_EXPLICIT | Destructed explicitly by destruct .
|
Object.DESTRUCT_NO_REFS | Destructed due to running out of references.
|
Object.DESTRUCT_GC | Destructed by the garbage collector.
|
Object.DESTRUCT_CLEANUP | Destructed as part of the cleanup when the pike process
exits. Occurs only if Pike has been compiled with the
configure option --with-cleanup-on-exit. See note
below.
|
|
- Note
Objects are normally not destructed when a process exits, so
destroy
functions aren't called then. Use atexit to get
called when the process exits.
- Note
Regarding destruction order during garbage collection:
If an object is destructed by the garbage collector, it's part of
a reference cycle with other things but with no external
references. If there are other objects with destroy
functions in the same cycle, it becomes a problem which to call
first.
E.g. if this object has a variable with another object which
(directly or indirectly) points back to this one, you might find
that the other object already has been destructed and the variable
thus contains zero.
The garbage collector tries to minimize such problems by defining
an order as far as possible:
If an object A contains an lfun::destroy and an object B does
not, then A is destructed before B.
If A references B single way, then A is destructed before B.
If A and B are in a cycle, and there is a reference somewhere
from B to A that is weaker than any reference from A to B, then
A is destructed before B.
If a cycle is resolved according to the rule above by ignoring a
weaker reference, and there is another ambiguous cycle that
would get resolved by ignoring the same reference, then the
latter cycle will be resolved by ignoring that reference.
Weak references (e.g. set with set_weak_flag() ) are
considered weaker than normal references, and both are
considered weaker than strong references.
Strong references are those from objects to the objects of their
lexically surrounding classes. There can never be a cycle
consisting only of strong references. (This means the gc never
destructs a parent object before all children have been
destructed.)
An example with well defined destruct order due to strong
references:
class Super {
class Sub {
protected void destroy() {
if (!Super::this)
error ("My parent has been destructed!\n");
}
}
Sub sub = Sub();
protected void destroy() {
if (!sub)
werror ("sub already destructed.\n");
}
}
The garbage collector ensures that these objects are destructed in
an order so that werror
in Super
is called and not
error
in Sub
.
- Note
When the garbage collector calls lfun::destroy , all accessible
non-objects and objects without destroy
functions are
still intact. They are not freed if the destroy
function
adds external references to them. However, all objects with
lfun::destroy in the cycle are already scheduled for
destruction and will therefore be destroyed even if external
references are added to them.
- Note
The garbage collector had completely random destruct order in
versions prior to 7.2.
- See also
lfun::create() , destruct()