Export to GitHub

python-safethread - Finalization.wiki


At a low level, python-safethread only supports weakrefs (no callbacks) and death notices. A death notice is when you create a death queue and ask it to watch a given object, then you check the queue to see when the object is deleted. The garbage collector never calls user code, simplifying it greatly.

Although this base mechanism is limited and awkward to use, it provides a basis for more powerful tools. object has been extended to use a __finalize__ method and a list of attributes specified in __finalizeattrs__. It can be utilized as follows:

``` from future import shared_module from threadtools import Monitor, monitormethod

class MyFile(Monitor): shared = True # More shared_module boilerplate, alas finalizeattrs = '_fd'

@monitormethod
def __finalize__(self):
    super().__finalize__()  # Disables automatic calling if you call __finalize__ manually
    os.close(self._fd)

```

What happens when you create a MyFile instance is a second object is created, using it to store _fd, while the main object has a property for _fd that redirects to this second ("core") object. When the main object gets deleted the system finalizer thread is notified (using a death queue), and it runs the "core" object's __finalize__ method. Since this happens in another thread, MyFile instances must be shareable, thus the use of Monitor and monitormethod.

The core benefit is that any arbitrary attributes will be gone by the time __finalize__ runs, making unfinalizable cycles much less likely. If something is unfinalizable, it's because it's still globally reachable through the system death queue. In the future a tool may be provided to report all reachable objects, and it would indicate any problems here.