[PD] variable receive objects?
Ivica Ico Bukvic
ico at vt.edu
Mon May 28 07:07:30 CEST 2012
On 05/28/2012 12:10 AM, Ivica Ico Bukvic wrote:
> Never mind. Just had a look at pd_bind/unbind code. This makes me
> wonder what if all bindings/unbindings were handled as lists? Would
> this potentially break anything (other than having to modify
> bind/unbind mechanism)? Does anything else depend on 2-member list vs.
> 1-member pointer in terms of bindings? I suspect there would be some
> cpu impact on having it implemented this way, but not that much.
>
Actually, please try attached patch. It fixes all such crashes for me on
pd-l2ork. Basically it has a static variable set within m_pd.c that is
turned on only when one of bindlist_<var>() functions is called in which
case any potential memory deallocation calls within pd_unbind are
deferred until all members of bindlist->b_list have been served with
data. After that bindlist_cleanup does its thing based on which members
have e_who pointing to NULL and that's that. In the event a call arrives
outside those bindlist_<var>() functions, it immediately deallocates
stuff as is currently the case with pd vanilla and extended.
Potential caveat: if one somehow invokes an event outside regular
execution of the code and it somehow arrives exactly during that narrow
span of time when the static var is enabled, its memory deallocation
will be ignored. I am however unsure if this is theoretically even
possible since my understanding is that the graph is never being
executed out-of-sync. Please correct me if I am wrong.
Cheers!
--
Ivica Ico Bukvic, D.M.A
Composition, Music Technology
Director, DISIS Interactive Sound& Intermedia Studio
Director, L2Ork Linux Laptop Orchestra
Head, ICAT Integrative Performance Studio
Virginia Tech
Department of Music
Blacksburg, VA 24061-0240
(540) 231-6139
(540) 231-5034 (fax)
disis.music.vt.edu
l2ork.music.vt.edu
ico.bukvic.net
-------------- next part --------------
--- m_pd.c.old 2012-05-28 00:55:52.616612895 -0400
+++ m_pd.c.new 2012-05-28 00:58:47.514606515 -0400
@@ -146,48 +146,95 @@
t_bindelem *b_list;
} t_bindlist;
+static int change_bindlist_via_graph = 0;
+
+static void bindlist_cleanup(t_bindlist *x)
+{
+ //fprintf(stderr,"bindlist_cleanup\n");
+ t_bindelem *e, *e2;
+ if (x->b_list->e_who == NULL)
+ {
+ e = x->b_list;
+ x->b_list = e->e_next;
+ freebytes(e, sizeof(t_bindelem));
+ //fprintf(stderr,"success B1a\n");
+ }
+ for (e = x->b_list; e2 = e->e_next; e = e2)
+ if (e2->e_who == NULL)
+ {
+ e->e_next = e2->e_next;
+ freebytes(e2, sizeof(t_bindelem));
+ //fprintf(stderr,"success B1b\n");
+ break;
+ }
+ if (!x->b_list->e_next)
+ {
+ freebytes(x->b_list, sizeof(t_bindelem));
+ pd_free(&x->b_pd);
+ //fprintf(stderr,"success B2\n");
+ }
+}
+
static void bindlist_bang(t_bindlist *x)
{
+ change_bindlist_via_graph = 1;
t_bindelem *e;
for (e = x->b_list; e; e = e->e_next)
pd_bang(e->e_who);
+ bindlist_cleanup(x);
+ change_bindlist_via_graph = 0;
}
static void bindlist_float(t_bindlist *x, t_float f)
{
+ change_bindlist_via_graph = 1;
t_bindelem *e;
for (e = x->b_list; e; e = e->e_next)
pd_float(e->e_who, f);
+ bindlist_cleanup(x);
+ change_bindlist_via_graph = 0;
}
static void bindlist_symbol(t_bindlist *x, t_symbol *s)
{
+ change_bindlist_via_graph = 1;
t_bindelem *e;
for (e = x->b_list; e; e = e->e_next)
pd_symbol(e->e_who, s);
+ bindlist_cleanup(x);
+ change_bindlist_via_graph = 0;
}
static void bindlist_pointer(t_bindlist *x, t_gpointer *gp)
{
+ change_bindlist_via_graph = 1;
t_bindelem *e;
for (e = x->b_list; e; e = e->e_next)
pd_pointer(e->e_who, gp);
+ bindlist_cleanup(x);
+ change_bindlist_via_graph = 0;
}
static void bindlist_list(t_bindlist *x, t_symbol *s,
int argc, t_atom *argv)
{
+ change_bindlist_via_graph = 1;
t_bindelem *e;
for (e = x->b_list; e; e = e->e_next)
pd_list(e->e_who, s, argc, argv);
+ bindlist_cleanup(x);
+ change_bindlist_via_graph = 0;
}
static void bindlist_anything(t_bindlist *x, t_symbol *s,
int argc, t_atom *argv)
{
+ change_bindlist_via_graph = 1;
t_bindelem *e;
for (e = x->b_list; e; e = e->e_next)
pd_typedmess(e->e_who, s, argc, argv);
+ bindlist_cleanup(x);
+ change_bindlist_via_graph = 0;
}
void m_pd_setup(void)
@@ -247,29 +294,53 @@
goes down to one, get rid of the bindlist and bind the symbol
straight to the remaining element. */
+ /* in pd-l2ork, we however also check whether changes to the bindlist
+ occur via graph (through code execution, e.g. dynamic change of receives)
+ and if so, we do not deallocate memory until the entire bindlist_<datatype>
+ function is complete with its execution, after which we call
+ bindlist_cleanup(). we control the execution via static int variable
+ change_bindlist_via_graph */
+
//fprintf(stderr,"pd_unbind option B %lx\n", (t_int)x);
t_bindlist *b = (t_bindlist *)s->s_thing;
t_bindelem *e, *e2;
if ((e = b->b_list)->e_who == x)
{
- b->b_list = e->e_next;
- freebytes(e, sizeof(t_bindelem));
+ if (change_bindlist_via_graph)
+ e->e_who = NULL;
+ else {
+ b->b_list = e->e_next;
+ freebytes(e, sizeof(t_bindelem));
+ }
//fprintf(stderr,"success B1a\n");
}
else for (e = b->b_list; e2 = e->e_next; e = e2)
if (e2->e_who == x)
{
- e->e_next = e2->e_next;
- freebytes(e2, sizeof(t_bindelem));
+ if (change_bindlist_via_graph)
+ e2->e_who = NULL;
+ else {
+ e->e_next = e2->e_next;
+ freebytes(e2, sizeof(t_bindelem));
+ }
//fprintf(stderr,"success B1b\n");
break;
}
- if (!b->b_list->e_next)
+
+ int count_valid = 0;
+ for (e = b->b_list; e; e = e->e_next)
{
+ if (e->e_who != NULL)
+ count_valid++;
+
+ }
+ if (count_valid == 1) {
s->s_thing = b->b_list->e_who;
- freebytes(b->b_list, sizeof(t_bindelem));
- pd_free(&b->b_pd);
+ if (!change_bindlist_via_graph) {
+ freebytes(b->b_list, sizeof(t_bindelem));
+ pd_free(&b->b_pd);
+ }
//fprintf(stderr,"success B2\n");
}
}
More information about the Pd-list
mailing list