diff --git a/src/m_pd.c b/src/m_pd.c index 0a0e4006b2fee739993384e50af772b7a7d2eed5..202b8e074a4b6d2d705169e0686b33dd42646c5e 100644 --- a/src/m_pd.c +++ b/src/m_pd.c @@ -146,48 +146,95 @@ typedef struct _bindlist 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) @@ -204,6 +251,7 @@ void m_pd_setup(void) 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 +265,7 @@ void pd_bind(t_pd *x, t_symbol *s) } 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 +285,7 @@ void pd_bind(t_pd *x, t_symbol *s) 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 +296,54 @@ void pd_unbind(t_pd *x, t_symbol *s) 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); - ///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);