>Finalize is called not only at the point of object
>destruction but also at the point of assignment, when the
>value is being overwritten.
Consider X := Y;
Just before its execution there are two separate and perhaps
differing object X and Y. The old X must first be destroyed
since it is going to go out of existence. For instance, if X
is on a linked list, it will need to be unlinked. So
Finalize is called. Then the area of memory formerly
occupied by X can be used for a copy of the bits of Y. At
this point there is only one object, Y, in existence, though
the same bit pattern may be present at X'address. But if,
say, Y was on a linked list, that list will only have Y, not
the copy. Then Adjust is called to turn the bit pattern at
X'address into a new object X. Continuing the linked list
example, Adjust would splice the new X into the list.
(Ignoring the stuff about a temp to allow X := X; to work.)
>which may cause Finalize to be called twice --
The RM explicitly mentions that Finalize may be called
multiple times, so the simple reference counting in the
example won't do. But you can add
Has_Been_Finalized : Boolean := False;
to the record definition and start Finalize with
if Obj.Has_Been_Finalized then return;
else Obj.Has_Been_Finalized := True;end if;
>Example #1, assume the spec of Final is as given
>...
>end
>.-1
>...
>But does this make sense? Null_Finis was never
>Initialized or Adjusted. Now my ref counts are
>messed up at the end.
I agree. It seems it should have been. And
removing 'constant', or moving from private
spec to body, or adding an 'aliased' component,
none seem to have any affect.
>this instead of returning Null_Finis:
>
> return (Controlled with null record);
Z
=1 in Create, assign to temp
.0 finalize (controlled with ... ??
=1 temp->Z1, Adjust
.0 finalize temp
:1 initialize Z2
.0 finalize Z2
=1 Z1->Z2, adjust
.0 finalize Z2
.-1 finalize Z1
end
>
>Still end up with that negative one! And all
>through this section of code, it never thinks
>I have two objects: my ref count is one at most
>the whole time.
If it had Initialized/Adjusted the (Controlled with ...)
object, or failed to Finalize it, then all would be well.
It seems clear that I/A shouldn't be called on a constant
aggregate (see RM 7.6(11)), but one would think neither
should Finalize. What happens if Finalize modifies (eg,
a Has_Been_Finalied flag) in the constant aggregate?