[PD] variable receive objects?
Ivica Ico Bukvic
ico at vt.edu
Thu Jun 21 00:09:22 CEST 2012
On 06/20/2012 05:38 PM, Miller Puckette wrote:
> [snip]
> I'm just saying that the automatic varable t_bindelem *e should be declared
> at the beginning of the block - no worries about change_bindlist_via_graph.
Ah, now I get it :-). Fixed.
> I think bindlist_bang() etc are more critical than pd_unbind as they naturally
> get called many times while a patch is running whereas pd_unbind is typically
> called only when objects are deleted. So moving checks from pd_unbind()
> to bindlist_bang() etc decreases pd's run-time efficiency.
>
> cheers
> M
OK, how about the attached patch where now I use the
change_bindlist_via_graph variable and increment it by one every time
something needs to be unbound so when you return back to the
bindlist_bang() or whatever call was issued, only if
change_bindlist_via_graph > 1 should it call unbind. Now it avoids
entering the bindlist_cleanup unless it absolutely has to...
Attached is also a patch that illustrates your case presented earlier
which crashed pd-l2ork prior to applying this latest version of the patch.
Cheers!
--
Ivica Ico Bukvic, D.M.A
Composition, Music Technology
Director, DISIS Interactive Sound& Intermedia Studio
Director, L2Ork Linux Laptop Orchestra
Head, ICAT IMPACT 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-06-20 17:51:43.845040884 -0400
+++ m_pd.c 2012-06-20 18:06:02.047009570 -0400
@@ -146,48 +146,101 @@
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)
{
t_bindelem *e;
+ change_bindlist_via_graph = 1;
for (e = x->b_list; e; e = e->e_next)
- pd_bang(e->e_who);
+ if (e->e_who != NULL) pd_bang(e->e_who);
+ if (change_bindlist_via_graph > 1)
+ bindlist_cleanup(x);
+ change_bindlist_via_graph = 0;
}
static void bindlist_float(t_bindlist *x, t_float f)
{
t_bindelem *e;
+ change_bindlist_via_graph = 1;
for (e = x->b_list; e; e = e->e_next)
- pd_float(e->e_who, f);
+ if (e->e_who != NULL) pd_float(e->e_who, f);
+ if (change_bindlist_via_graph > 1)
+ bindlist_cleanup(x);
+ change_bindlist_via_graph = 0;
}
static void bindlist_symbol(t_bindlist *x, t_symbol *s)
{
t_bindelem *e;
+ change_bindlist_via_graph = 1;
for (e = x->b_list; e; e = e->e_next)
- pd_symbol(e->e_who, s);
+ if (e->e_who != NULL) pd_symbol(e->e_who, s);
+ if (change_bindlist_via_graph > 1)
+ bindlist_cleanup(x);
+ change_bindlist_via_graph = 0;
}
static void bindlist_pointer(t_bindlist *x, t_gpointer *gp)
{
t_bindelem *e;
+ change_bindlist_via_graph = 1;
for (e = x->b_list; e; e = e->e_next)
- pd_pointer(e->e_who, gp);
+ if (e->e_who != NULL) pd_pointer(e->e_who, gp);
+ if (change_bindlist_via_graph > 1)
+ bindlist_cleanup(x);
+ change_bindlist_via_graph = 0;
}
static void bindlist_list(t_bindlist *x, t_symbol *s,
int argc, t_atom *argv)
{
t_bindelem *e;
+ change_bindlist_via_graph = 1;
for (e = x->b_list; e; e = e->e_next)
- pd_list(e->e_who, s, argc, argv);
+ if (e->e_who != NULL) pd_list(e->e_who, s, argc, argv);
+ if (change_bindlist_via_graph > 1)
+ bindlist_cleanup(x);
+ change_bindlist_via_graph = 0;
}
static void bindlist_anything(t_bindlist *x, t_symbol *s,
int argc, t_atom *argv)
{
t_bindelem *e;
+ change_bindlist_via_graph = 1;
for (e = x->b_list; e; e = e->e_next)
- pd_typedmess(e->e_who, s, argc, argv);
+ if (e->e_who != NULL) pd_typedmess(e->e_who, s, argc, argv);
+ if (change_bindlist_via_graph > 1)
+ bindlist_cleanup(x);
+ change_bindlist_via_graph = 0;
}
void m_pd_setup(void)
@@ -204,6 +257,7 @@
void pd_bind(t_pd *x, t_symbol *s)
{
+ //fprintf(stderr,"pd_bind %s\n", s->s_name);
if (s->s_thing)
{
if (*s->s_thing == bindlist_class)
@@ -217,7 +271,7 @@
}
else
{
- //fprintf(stderr,"pd_unbind option 1B %lx\n", (t_int)x);
+ //fprintf(stderr,"pd_bind option 1B %lx\n", (t_int)x);
t_bindlist *b = (t_bindlist *)pd_new(bindlist_class);
t_bindelem *e1 = (t_bindelem *)getbytes(sizeof(t_bindelem));
t_bindelem *e2 = (t_bindelem *)getbytes(sizeof(t_bindelem));
@@ -237,6 +291,7 @@
void pd_unbind(t_pd *x, t_symbol *s)
{
+ //fprintf(stderr,"pd_unbind %s\n", s->s_name);
if (s->s_thing == x) {
//fprintf(stderr,"pd_unbind option A %lx\n", (t_int)x);
s->s_thing = 0;
@@ -247,30 +302,56 @@
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) {
+ 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) {
+ 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);
- ///fprintf(stderr,"success B3\n");
+ if (!change_bindlist_via_graph) {
+ freebytes(b->b_list, sizeof(t_bindelem));
+ pd_free(&b->b_pd);
+ }
+ //fprintf(stderr,"success B2\n");
}
}
else pd_error(x, "%s: couldn't unbind", s->s_name);
-------------- next part --------------
A non-text attachment was scrubbed...
Name: test3.pd
Type: application/puredata
Size: 460 bytes
Desc: not available
URL: <http://lists.puredata.info/pipermail/pd-list/attachments/20120620/cfbb4b43/attachment.bin>
More information about the Pd-list
mailing list