[PD] variable receive objects?

Miller Puckette msp at ucsd.edu
Sat Jun 23 00:09:28 CEST 2012


Hmm.. I'm still looking for a solution that doesn't require adding extra
stuff to bindlist_bang() etc.

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 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);





More information about the Pd-list mailing list