Updated information on Dianne Hackborn's old vref proposal. A copy of

her original proposal has been included as an appendix, since it is hard
to get since DejaNews lost their old archives.
This commit is contained in:
Fred Drake 2000-11-17 22:54:45 +00:00
parent 655cf91b3a
commit 7626095211
1 changed files with 150 additions and 12 deletions

View File

@ -103,17 +103,14 @@ Weak References in Java
Previous Weak Reference Work in Python
Diane Hackborn's vref proposal. 'vref' objects were very similar
to java.lang.ref.WeakReference objects, except there was no
equivalent to the invalidation queues. Implementing a "weak
dictionary" would be just as difficult as using only weak
references (without the invalidation queue) in Java. Information
on this has disappeared from the Web. Original discussion
occurred in the comp.lang.python newsgroup; a good archive of that
may turn up something more.
Dianne doesn't have any record of her proposal, and doesn't recall
doing an implementation.
Dianne Hackborn's proposed something called "virtual references".
'vref' objects were very similar to java.lang.ref.WeakReference
objects, except there was no equivalent to the invalidation
queues. Implementing a "weak dictionary" would be just as
difficult as using only weak references (without the invalidation
queue) in Java. Information on this has disappeared from the Web.
Original discussion occurred in the comp.lang.python newsgroup; a
good archive of that may turn up something more.
Marc-André Lemburg's mx.Proxy package. These Web pages appear to
be unavailable at the moment.
@ -127,12 +124,21 @@ Previous Weak Reference Work in Python
http://www.handshake.de/~dieter/weakdict.html
PyWeakReference by Alex Shindich:
http://sourceforge.net/projects/pyweakreference/
Possible Applications
PyGTK+ bindings?
Tkinter?
Tkinter -- could avoid circular references by using weak
references from widgets to their parents. Objects won't be
discarded any sooner in the typical case, but there won't be so
much dependence on the programmer calling .destroy() before
releasing a reference. This would mostly benefit long-running
applications.
DOM trees?
@ -142,6 +148,138 @@ Proposed Implementation
XXX -- Not yet.
Appendix -- Dianne Hackborn's vref proposal (1995)
[This has been indented and paragraphs reflowed, but there have be
no content changes. --Fred]
Proposal: Virtual References
In an attempt to partly address the recurring discussion
concerning reference counting vs. garbage collection, I would like
to propose an extension to Python which should help in the
creation of "well structured" cyclic graphs. In particular, it
should allow at least trees with parent back-pointers and
doubly-linked lists to be created without worry about cycles.
The basic mechanism I'd like to propose is that of a "virtual
reference," or a "vref" from here on out. A vref is essentially a
handle on an object that does not increment the object's reference
count. This means that holding a vref on an object will not keep
the object from being destroyed. This would allow the Python
programmer, for example, to create the aforementioned tree
structure tree structure, which is automatically destroyed when it
is no longer in use -- by making all of the parent back-references
into vrefs, they no longer create reference cycles which keep the
tree from being destroyed.
In order to implement this mechanism, the Python core must ensure
that no -real- pointers are ever left referencing objects that no
longer exist. The implementation I would like to propose involves
two basic additions to the current Python system:
1. A new "vref" type, through which the Python programmer creates
and manipulates virtual references. Internally, it is
basically a C-level Python object with a pointer to the Python
object it is a reference to. Unlike all other Python code,
however, it does not change the reference count of this object.
In addition, it includes two pointers to implement a
doubly-linked list, which is used below.
2. The addition of a new field to the basic Python object
[PyObject_Head in object.h], which is either NULL, or points to
the head of a list of all vref objects that reference it. When
a vref object attaches itself to another object, it adds itself
to this linked list. Then, if an object with any vrefs on it
is deallocated, it may walk this list and ensure that all of
the vrefs on it point to some safe value, e.g. Nothing.
This implementation should hopefully have a minimal impact on the
current Python core -- when no vrefs exist, it should only add one
pointer to all objects, and a check for a NULL pointer every time
an object is deallocated.
Back at the Python language level, I have considered two possible
semantics for the vref object --
==> Pointer semantics:
In this model, a vref behaves essentially like a Python-level
pointer; the Python program must explicitly dereference the vref
to manipulate the actual object it references.
An example vref module using this model could include the
function "new"; When used as 'MyVref = vref.new(MyObject)', it
returns a new vref object such that that MyVref.object ==
MyObject. MyVref.object would then change to Nothing if
MyObject is ever deallocated.
For a concrete example, we may introduce some new C-style syntax:
& -- unary operator, creates a vref on an object, same as vref.new().
* -- unary operator, dereference a vref, same as VrefObject.object.
We can then define:
1. type(&MyObject) == vref.VrefType
2. *(&MyObject) == MyObject
3. (*(&MyObject)).attr == MyObject.attr
4. &&MyObject == Nothing
5. *MyObject -> exception
Rule #4 is subtle, but comes about because we have made a vref
to (a vref with no real references). Thus the outer vref is
cleared to Nothing when the inner one inevitably disappears.
==> Proxy semantics:
In this model, the Python programmer manipulates vref objects
just as if she were manipulating the object it is a reference
of. This is accomplished by implementing the vref so that all
operations on it are redirected to its referenced object. With
this model, the dereference operator (*) no longer makes sense;
instead, we have only the reference operator (&), and define:
1. type(&MyObject) == type(MyObject)
2. &MyObject == MyObject
3. (&MyObject).attr == MyObject.attr
4. &&MyObject == MyObject
Again, rule #4 is important -- here, the outer vref is in fact a
reference to the original object, and -not- the inner vref.
This is because all operations applied to a vref actually apply
to its object, so that creating a vref of a vref actually
results in creating a vref of the latter's object.
The first, pointer semantics, has the advantage that it would be
very easy to implement; the vref type is extremely simple,
requiring at minimum a single attribute, object, and a function to
create a reference.
However, I really like the proxy semantics. Not only does it put
less of a burden on the Python programmer, but it allows you to do
nice things like use a vref anywhere you would use the actual
object. Unfortunately, it would probably an extreme pain, if not
practically impossible, to implement in the current Python
implementation. I do have some thoughts, though, on how to do
this, if it seems interesting; one possibility is to introduce new
type-checking functions which handle the vref. This would
hopefully older C modules which don't expect vrefs to simply
return a type error, until they can be fixed.
Finally, there are some other additional capabilities that this
system could provide. One that seems particularily interesting to
me involves allowing the Python programmer to add "destructor"
function to a vref -- this Python function would be called
immediately prior to the referenced object being deallocated,
allowing a Python program to invisibly attach itself to another
object and watch for it to disappear. This seems neat, though I
haven't actually come up with any practical uses for it, yet... :)
-- Dianne
Copyright
This document has been placed in the public domain.