[PD] variable receive objects?

Ivica Ico Bukvic ico at vt.edu
Sun Jun 24 00:36:44 CEST 2012



Miller Puckette <msp at 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 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);


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



More information about the Pd-list mailing list