On 06/20/2012 01:53 PM, Miller Puckette wrote:
Hi Ico and list - On Tue, Jun 19, 2012 at 10:20:07PM -0400, Ivica Ico Bukvic wrote:
-----Original Message----- From: Miller Puckette [mailto:msp@ucsd.edu] Sent: Tuesday, June 19, 2012 5:11 PM To: Ivica Ico Bukvic Cc: 'Claude Heiland-Allen'; Hans-Christoph Steiner; pd-list@iem.at Subject: Re: [PD] variable receive objects?
I don't think your patch works in every case (I think you simply have to
check
every e->e_who inside functions like bindlist_bang() before dereferencing them since someone could clear one of them while inside a previous one).
Thanks for the update, Miller. Is there a way you could give me an example patch that would fail this way? I ask this simply because I am unable to imagine one you describe here. Namely, even if a parent's send has been changed by the child-of-a-child object this way, this change would only make specific instance point to null object but its pointer would be still valid until its entire sub-tree has been navigated, and only after its entire sub-tree has been navigated would it be actually dereferencing stuff and fixing the pointers accordingly before the next incoming wave of calls.
I don't have an example handy but here's a stack pseudo-trace:
... bindlist_bang() pd_bang(first item in bindlist) ... toggle_receive()<--- zeros out second item in bindlist
You're right, there should be one more check before calling pd_bang or pd_whatever simply stating
if (e->e_who != NULL) pd_whatever(e->e_who);
Beyond that, it should work as only e structs that have been slated for deallocation will have that one set to NULL while still having a valid pointer to the rest of the list so as to avoid the crash.
then when pd_bang returns, bindlist_bang proceeds to dereference second item in bindlist and... not bang but more like 'boom'.
Also, there are declarations after functional lines, e.g.,
- change_bindlist_via_graph = 1; t_bindelem *e;
which is not standard C - something I frequently have to clean up in
people's
patches :)
You mean declaration of a global variable needs to be placed at the top of the source file? Sure, that is an easy fix. It's been placed here in proximity to make the patch more legible.
It's an automatic variable whose declaration should be at the beginning of a block. Otherwise Visual C++ seems to get offended (and I don't find out until I crank up my stupid windows machine :)
But it is declared as a global variable at the beginning of the diff so it is not an automatic variable that is destroyed after function exits:
+static int change_bindlist_via_graph = 0;
+static void bindlist_cleanup(t_bindlist *x)
Are you saying that I need to re-declare it within the function? If so, that is the first time I would've seen anything like it and it is something certainly the rest of the Pd code does not conform to, either (or at least pd-extended).
I think something like what you proposed could work; there would still be
a
performance hit which I'd probably want to measure before committing to doing this... since after all we're just talking about a wierd and
obnoxious
'feature' in IEMGUIs that I would simply take out if I could :)
I am not so sure there is a performance hit since in both cases dereferencing happens in exactly the same way, except in this one the referencing is delayed and in the interim structs destined to be dereferenced are made to point to null and then skipped if a subsequent call trips over a null-pointing struct before it has been dereferenced. As such its performance impact should be minimal.
Main performance hit would be that every time anyone traverses a bindlist (many send/receive messages, perhaps most) there's all that extra code in bindlist_bang(), etc. needed to make the extra tests (possible zero receiver and possible cleanup needed afterward).
Clean-up afterward is already implemented and is done within bindlist_cleanup() call which is nearly identical in terms of its workload to what was originally placed within pd_unbind, so I seriously doubt this will make much if any difference.
What will potentially add a bit of an overhead is the call above that I forgot to add:
if (e->e_who != NULL) pd_whatever(e->e_who);
I honestly have no idea how much a single if statement checking for a null pointer requires in terms of CPU usage. That said, FWIW I seriously doubt that this one if would cause that much of cpu overhead even if executed on a large number of calls.
cheers M