Miller Puckette msp@ucsd.edu wrote:
Hmm.. I'm still looking for a solution that doesn't require adding extra stuff to bindlist_bang() etc.
In the meantime for those eager to work with dynamic receives, the fix below is now in the pd-l2otk trunk on the github.
Coming up next in the land o' pd-l2ork, universal presets ;-)
Best wishes,
Ico
cheers M
On Wed, Jun 20, 2012 at 06:09:22PM -0400, Ivica Ico Bukvic wrote:
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
--- 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 thebindlist
occur via graph (through code execution, e.g. dynamic change ofreceives)
and if so, we do not deallocate memory until the entirebindlist_<datatype>
function is complete with its execution, after which we callbindlist_cleanup(). we control the execution via static intvariable
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);} } else pd_error(x, "%s: couldn't unbind", s->s_name);//fprintf(stderr,"success B2\n"); }
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