Juergen Boemmels wrote: > > Benjamin Goldberg <[EMAIL PROTECTED]> writes: > > > I would like for Parrot to have some way of creating Weak References; > > I think that this is probably a vital feature. > > > > The way I envision this is as follows. The following typedef and new > > function would be added: > > > > typedef void (*pobject_died_cb)(INTERP, PMC* who_asked, > > Pobj* weakref, void *callback_info); > > void pobject_weakref(INTERP, pobject_died_cb callback, > > Pobj* weakref, void *callback_info); > > This might be sometimes useful. Keeping a container of active objects > like filehandles or windows for example. In this case it can't mark > the reference because this would make the object active forever. > > > Inside of a PMC*'s mark method, it registers callbacks (using the > > above function) so that it will be informed about what to do if the > > object to which it weakly refers to is found to not be alive at the > > end of the DOD sweep. > > This does not need to go into the mark function. The weakref_callback > code can be called inside the destroy function. Im not sure if it > should be called befor or after the custom destroy-function is > run. And is the order of the weakref_callbacks defined. > > > The pobject_weakref function first checks if the 'weakref' argument > > has been marked as alive -- if so, nothing happens. Then, it adds the > > Pobj* to a lookup table, pointing from the Pobj*, to a list of > > registered callbacks for that Pobj*. > > This is far to complicated. Each object has a list of > destroy-functions, one of them is the costom-destroy function the > others are the weakref-callbacks.
But suppose that at the end of DoD, the object we're weakly referring to gets marked as alive? Now, we would need to look through that object's list of destroy-functions, and remove all of the weakref-callbacks. But if the weakref-callbacks are stored in a seperate data structure, created during DoD, then there's no problem; this data structure will get re-created for each DoD pass, and thus always start empty. Also, by keeping them seperate, we can walk all the callback functions before destructing the dead objects. (But you're right -- it is too complicated to do a lookup table. A simple linked list should do fine.) > But one other thing, what happens if the object holding the weakref > dies before the refrenced object? Then the callback-function will be > called for a dead object. Each callback-function "belongs" to a pmc. The DoD should be able to know this, and act on it. So if the pmc which registered the callback is dead, (or if the object weakly referred has since then come alive), then the callback isn't called. > So pobject_weakref() needs to return a handle > for the weakref and there needs to be a function > weakref_destroy(weakref_handle *handle). > > Other issue is who owns the data_structure of the weakref? The > referent, the referee, or will this be garbage-collected (which makes > the weakref_handle a PObj* and weakref_destroy its custom destroy > function. The garbage collector owns everything except for callback_info, which belongs to the pmc which registered the weakref-callback. > > After DOD finishes, the lookup table is walked; for each entry whose > > Pobj* hasn't been marked as alive, the callbacks are called. > > > > The effect of this of course is that a WeakRef has no cost except > > during Dead Object Detection. > > It only has a cost at object destroy-time. (If the weakrefs are > garbagecollected they have an effect on DOD in the way that there are > more objects to trace) *blink* More objects? Oh, you're assuming that pobject_weakref is returning a Pobj* handle. Keeping the callback data in a seperate list which only exists for the duration of the dod prevents this. Or rather, you do have to clean up the linked list, of course, but there's no extra bookkeeping. > > The first, perhaps most important use, would be to implement a > > string-interning table. > > > > You'd have a global (per-interpreter) pmc which contains a hashtable > > of cstrings to perlstrings; if the cstring is present, the > > corresponding perlstring is returned; otherwise a new perlstring would > > be created and added to the table, then returned. If any of the > > perlstrings go out of scope, then their hash entries should disappear > > from the table. Obivously, if the table contained normal references > > to the strings, then they won't ever go out of scope. And if the > > table simply doesn't mark them as alive, it wouldn't know when they're > > dead. But with weakrefs, this is easy. > > this is only useful if a hashlookup is fast compared with > string_make. Well, it might be. Hashing can be quite fast, ya know. Here's a better idea, one you'll have more difficulty arguing with -- imagine a debugger, written in parrot. We are going to have one, right? Hmm, p6tkdb :) It needs to keep references to objects it's interested in, but if they're strong references, then we would have trouble debugging objects with custom destroys (or worse, objects needing timely destruction), since the debugger's references to them would prevent them from being cleaned up. Changing to weakrefs removes this kind of horrible heisenbug. -- $a=24;split//,240513;s/\B/ => /for@@=qw(ac ab bc ba cb ca );{push(@b,$a),($a-=6)^=1 for 2..$a/6x--$|;print "[EMAIL PROTECTED] ]\n";((6<=($a-=6))?$a+=$_[$a%6]-$a%6:($a=pop @b))&&redo;}