.. mode: -*- rst -*- Finalization ============ :Tag: design.mps.finalize :Author: David Jones :Date: 1997-02-14 :Status: complete design :Revision: $Id: //info.ravenbrook.com/project/mps/master/design/finalize.txt#15 $ :Copyright: See `Copyright and License`_. :Index terms: pair: finalization; design Overview -------- _`.overview`: Finalization is implemented internally using the MRG pool class (design.mps.poolmrg_). Objects can be registered for finalization by calling ``mps_finalize()``. Notification of finalization is given to the client via the messaging interface (design.mps.message_). The MRG pool class implements a ``Message`` subclass which implements the finalization messages. .. _design.mps.poolmrg: poolmrg .. _design.mps.message: message Requirements ------------ _`.req`: Historically only Dylan had requirements for finalization, see req.dylan.fun.final_. Now (2003-02-19) Configura have requirements for finalization. Happily they are very similar. .. _req.dylan.fun.final: https://info.ravenbrook.com/project/mps/import/2001-09-27/mminfo/doc/req/dylan Implementation -------------- _`.impl.over`: Registering an object for finalization corresponds to allocating a reference of rank FINAL to that object. This reference is allocated in a guardian object in a pool belonging to the MRG pool class (see design.mps.poolmrg_). .. _design.mps.poolmrg: poolmrg _`.impl.arena.struct`: A single pool belonging to the MRG pool class and used for managing final references is kept in the arena and referred to as the "final pool". _`.impl.arena.lazy`: The final pool is lazily created. It is not created until the first object is registered for finalization. _`.impl.arena.flag`: There is a flag in the Arena that indicates whether the final pool has been created yet or not. _`.impl.scan`: An object is determined to be finalizable if it is fixed at rank FINAL for a trace, and was not fixed at any lower rank for that trace. See design.mps.poolmrg.scan.wasold_. .. _design.mps.poolmrg.scan.wasold: poolmrg#.scan.wasold _`.impl.message`: When an object is determined to be finalizable, a message for that object is posted to the arena's message queue. _`.impl.arena-destroy.empty`: ``ArenaDestroy()`` empties the message queue by calling ``MessageEmpty()``. _`.impl.arena-destroy.final-pool`: If the final pool has been created then ``ArenaDestroy()`` destroys the final pool. _`.impl.access`: ``mps_message_finalization_ref()`` needs to access the finalization message to retrieve the reference and then write it to where the client asks. This must be done carefully, in order to avoid invalidating collection invariants such as the segment summary. _`.impl.invariants`: We protect the invariants by using ``ArenaRead()`` and ``ArenaWrite()`` to read and write the reference via the software barrier. External interface ------------------ _`.if.register`: ``mps_finalize()`` registers an object for finalization. _`.if.deregister`: ``mps_definalize()`` deregisters an object for finalization. It is an error to definalize an object that has not been registered for finalization. _`.if.get-ref`: ``mps_message_finalization_ref()`` returns the reference to the finalized object stored in the finalization message. _`.if.multiple`: The external interface allows an object to be registered multiple times, but does not specify the number of finalization messages that will be posted for that object. Internal interface ------------------ ``Res ArenaFinalize(Arena arena, Ref addr)`` _`.int.finalize.create`: Creates the final pool if it has not been created yet. _`.int.finalize.alloc`: Allocates a guardian in the final pool. _`.int.finalize.alloc.multiple`: A consequence of this implementation is that if an object is finalized multiple times, then multiple guardians are created in the final pool, and so multiple messages will be posted to the message queue when the object is determined to be finalizable. But this behaviour is not guaranteed by the documentation, leaving us free to change the iplementation. _`.int.finalize.write`: Writes a reference to the object into the guardian object. _`.int.finalize.all`: That's all. _`.int.finalize.error`: If either the creation of the pool or the allocation of the object fails then the error is returned to the caller. _`.int.finalize.error.no-unwind`: This function does not need to do any unwinding in the error cases because the creation of the pool is not something that needs to be undone. ``Res ArenaDefinalize(Arena arena, Ref obj)`` _`.int.definalize.fail`: If the final pool has not been created, return ``ResFAIL`` immediately. _`.int.definalize.search`: Otherwise, search for a guardian in the final pool that refers to the object and which has not yet been finalized. If one is found, delete it and return ``ResOK``. Otherwise no guardians in the final pool refer to the object, so return ``ResFAIL``. Document History ---------------- - 1997-02-14 David Jones. Incomplete design. - 2002-06-07 RB_ Converted from MMInfo database design document. - 2013-04-13 GDR_ Converted to reStructuredText. .. _RB: https://www.ravenbrook.com/consultants/rb/ .. _GDR: https://www.ravenbrook.com/consultants/gdr/ Copyright and License --------------------- Copyright © 2013–2020 `Ravenbrook Limited `_. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.