diff --git a/src/g_canvas.c b/src/g_canvas.c index 17c2acc15c3c84d8bb6357ff3971e1ce99cda41b..1615f84e2ee93e4d527e52bb562d3be96b2e2db3 100644 --- a/src/g_canvas.c +++ b/src/g_canvas.c @@ -343,12 +343,42 @@ void glist_init(t_glist *x) x->gl_ylabel = (t_symbol **)t_getbytes(0); } +/* global var used by pd_new() to work with redundant memory, originally defined in m_pd.c */ +extern int canvas_check_duplicate; + /* make a new glist. It will either be a "root" canvas or else it appears as a "text" object in another window (canvas_getcurrent() tells us which.) */ t_canvas *canvas_new(void *dummy, t_symbol *sel, int argc, t_atom *argv) { + /* first alloc one byte or redundant memory to prevent creation of objects with the same "name" + which leads to double-action invoked from every single action and eventually possible crashes + we keep a list of these redundant allocations and destroy them when pd quits */ + + //if (x->gl_owner && x->gl_env) { + + t_redundant_mem *new_rm = (t_redundant_mem *)t_getbytes(sizeof(*new_rm)); + //new_rm->rm_what = (int)getbytes(1); + if (rm_start == NULL) { + //fprintf(stderr,"first allocation\n"); + rm_start = new_rm; + rm_end = new_rm; + } + else if (rm_start == rm_end) { + //fprintf(stderr,"second allocation\n"); + rm_end = new_rm; + rm_start->rm_next = rm_end; + } + else { + //fprintf(stderr,"allocation\n"); + rm_end->rm_next = new_rm; + rm_end = new_rm; + } + //} + + canvas_check_duplicate = -1; t_canvas *x = (t_canvas *)pd_new(canvas_class); + rm_end->rm_canvas = x; t_canvas *owner = canvas_getcurrent(); t_symbol *s = &s_; int vis = 0, width = GLIST_DEFCANVASWIDTH, height = GLIST_DEFCANVASHEIGHT; @@ -876,7 +906,7 @@ void canvas_free(t_canvas *x) if (x->gl_magic_glass) magicGlass_free(x->gl_magic_glass); - canvas_noundo(x); + //canvas_noundo(x); canvas_undo_free(x); if (canvas_editing == x) @@ -889,8 +919,10 @@ void canvas_free(t_canvas *x) if (x == glist_getcanvas(x)) canvas_vis(x, 0); - if (strcmp(x->gl_name->s_name, "Pd")) + if (strcmp(x->gl_name->s_name, "Pd")) { + //fprintf(stderr,"canvas_free calling pd_unbind\n"); pd_unbind(&x->gl_pd, canvas_makebindsym(x->gl_name)); + } if (x->gl_env) { freebytes(x->gl_env->ce_argv, x->gl_env->ce_argc * sizeof(t_atom)); diff --git a/src/g_canvas.h b/src/g_canvas.h index b7e5881ba99211420992a5b0b6f89139e80ca52c..57a2ca893cf2f0ff7733b6c2dac2e6d568197f8f 100644 --- a/src/g_canvas.h +++ b/src/g_canvas.h @@ -46,17 +46,17 @@ extern "C" { canvases/abstractions rather than individual objects. the queue is destructed in m_glob.c quit call (when pd exits) */ -/* + typedef struct _redundant_mem { - int rm_what; + //int rm_what; t_canvas *rm_canvas; struct _redundant_mem *rm_next; } t_redundant_mem; t_redundant_mem *rm_start; t_redundant_mem *rm_end; -*/ + /* --------------------- geometry ---------------------------- */ #define IOWIDTH 7 /* width of an inlet/outlet in pixels */ diff --git a/src/m_pd.c b/src/m_pd.c index 00e06c77366f99f5f41537f4e26d8e6ff7c3920b..dd9589cdd2639480c58b72fbee3fa88c6b54a1bb 100644 --- a/src/m_pd.c +++ b/src/m_pd.c @@ -11,9 +11,16 @@ /* FIXME no out-of-memory testing yet! */ +int canvas_check_duplicate = 0; + +extern t_redundant_mem *rm_start; +extern t_redundant_mem *rm_end; + t_pd *pd_new(t_class *c) { - t_pd *x; + t_pd *x = NULL; + t_pd *y = NULL; + if (!c) bug ("pd_new: apparently called before setup routine"); @@ -31,41 +38,47 @@ t_pd *pd_new(t_class *c) a random additional amount of memory and then resize allocation to the original size - duplicate: -1 initial state - 0 all is ok + duplicate: -1 enable check state + 0 all is ok (or we are not allocating canvas memory) 1 found a duplicate */ -/* - int duplicate = 0; //change to -1 to enable redundant_mem resizing - int random_extra = 0; + //int random_extra = 0; + //int random_offset = 1; - while (duplicate != 0) { + while (canvas_check_duplicate != 0) { - if (duplicate == -1) { - //fprintf(stderr,"alloc %d %d\n", duplicate, (int)c->c_size); + if (canvas_check_duplicate == -1) { + //fprintf(stderr,"alloc %d %d\n", canvas_check_duplicate, (int)c->c_size); x = (t_pd *)t_getbytes(c->c_size); - } else if (duplicate == 1) { - random_extra = rand () + 1; - //fprintf(stderr,"alloc %d %d %d\n", duplicate, (int)c->c_size, (int)c->c_size + random_extra); - x = (t_pd *)t_getbytes(c->c_size + random_extra); + } else if (canvas_check_duplicate == 1) { + //random_extra = rand () + random_offset; + //fprintf(stderr,"alloc %d %d %d\n", canvas_check_duplicate, (int)c->c_size, (int)c->c_size + random_extra); + //x = (t_pd *)t_getbytes(c->c_size + random_extra); + //fprintf(stderr,"duplicate\n"); + y = x; + y = (t_pd *)t_resizebytes(x, c->c_size, 1); + x = (t_pd *)t_getbytes(c->c_size); + t_freebytes(y, sizeof(1)); } - duplicate = 0; + canvas_check_duplicate = 0; if (rm_start) { t_redundant_mem *tmp = rm_start; while (tmp->rm_next) { - if ((int)tmp->rm_canvas == (int)x) { - duplicate = 1; + //fprintf(stderr,"compare %lx %lx\n", (t_int)tmp->rm_canvas, (t_int)x); + if ((t_int)tmp->rm_canvas == (t_int)x) { + canvas_check_duplicate = 1; break; } tmp = tmp->rm_next; } - if (tmp && (int)tmp->rm_canvas == (int)x) - duplicate = 1; + if (tmp && (t_int)tmp->rm_canvas == (t_int)x) + canvas_check_duplicate = 1; } - //fprintf(stderr,"done alloc %d\n", duplicate); - if (duplicate == 1) { + + //fprintf(stderr,"done alloc %d\n", canvas_check_duplicate); + /*if (canvas_check_duplicate == 1) { //fprintf(stderr,"duplicate\n"); if (!random_extra) t_freebytes(x, sizeof(c->c_size)); @@ -73,13 +86,13 @@ t_pd *pd_new(t_class *c) t_freebytes(x, sizeof(c->c_size+random_extra)); } - if (!duplicate && random_extra) { + if (!canvas_check_duplicate && random_extra) { x = (t_pd *)t_resizebytes(x, c->c_size+random_extra, c->c_size); - } + break; + }*/ } -*/ - x = (t_pd *)t_getbytes(c->c_size); + if (!x) x = (t_pd *)t_getbytes(c->c_size); *x = c; if (c->c_patchable) { @@ -193,6 +206,7 @@ void pd_bind(t_pd *x, t_symbol *s) { if (*s->s_thing == bindlist_class) { + //fprintf(stderr,"pd_bind option 1A %lx\n", (t_int)x); t_bindlist *b = (t_bindlist *)s->s_thing; t_bindelem *e = (t_bindelem *)getbytes(sizeof(t_bindelem)); e->e_next = b->b_list; @@ -201,6 +215,7 @@ void pd_bind(t_pd *x, t_symbol *s) } else { + //fprintf(stderr,"pd_unbind 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)); @@ -212,30 +227,40 @@ void pd_bind(t_pd *x, t_symbol *s) s->s_thing = &b->b_pd; } } - else s->s_thing = x; + else { + //fprintf(stderr,"pd_bind option 2 %lx\n", (t_int)x); + s->s_thing = x; + } } void pd_unbind(t_pd *x, t_symbol *s) { - if (s->s_thing == x) s->s_thing = 0; + if (s->s_thing == x) { + //fprintf(stderr,"pd_unbind option A %lx\n", (t_int)x); + s->s_thing = 0; + } else if (s->s_thing && *s->s_thing == bindlist_class) { /* bindlists always have at least two elements... if the number goes down to one, get rid of the bindlist and bind the symbol straight to the remaining element. */ + //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)); + //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)); + //fprintf(stderr,"success B1b\n"); break; } if (!b->b_list->e_next) @@ -243,6 +268,7 @@ void pd_unbind(t_pd *x, t_symbol *s) 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"); } } else pd_error(x, "%s: couldn't unbind", s->s_name);