Commit f57259d6 authored by Jonathan Wilkes's avatar Jonathan Wilkes
Browse files

speed up msg box by caching the glist in t_messresponder for fetching $0

This brings msg box back to the same performance it had before $0 expansion
was added as a feature to message boxes.

The first implementation relied on calling canvas_setcurrent and
canvas_unsetcurrent in the message box methods. This added a malloc/free
for each message box method call.

Instead this implementation caches the msg box glist in the t_messresponder.
That is available as the target parameter in m_binbuf. Unfortunately, we
have to add a parameter to binbuf_realizedollsym. Since that's a public
function we have to break out the new param into binbuf_dorealizedollsym.
parent ff8afc1c
...@@ -155,10 +155,20 @@ t_canvasenvironment *canvas_getenv(t_canvas *x) ...@@ -155,10 +155,20 @@ t_canvasenvironment *canvas_getenv(t_canvas *x)
return (x->gl_env); return (x->gl_env);
} }
int canvas_getdollarzero( void) extern t_class *messresponder_class;
extern t_glist *messresponder_getglist(t_pd *x);
int canvas_getdollarzero(t_pd *x)
{ {
t_canvas *x = canvas_getcurrent(); t_canvas *cnv;
t_canvasenvironment *env = (x ? canvas_getenv(x) : 0); /* binbuf_eval can send us a NULL target... */
if (x && pd_class(x) == messresponder_class)
{
cnv = messresponder_getglist(x);
}
else
cnv = canvas_getcurrent();
t_canvasenvironment *env = (cnv ? canvas_getenv(cnv) : 0);
if (env) if (env)
return (env->ce_dollarzero); return (env->ce_dollarzero);
else return (0); else return (0);
......
...@@ -550,6 +550,7 @@ void canvas_objfor(t_glist *gl, t_text *x, int argc, t_atom *argv) ...@@ -550,6 +550,7 @@ void canvas_objfor(t_glist *gl, t_text *x, int argc, t_atom *argv)
typedef struct _messresponder typedef struct _messresponder
{ {
t_pd mr_pd; t_pd mr_pd;
t_glist *mr_glist;
t_outlet *mr_outlet; t_outlet *mr_outlet;
} t_messresponder; } t_messresponder;
...@@ -561,7 +562,7 @@ typedef struct _message ...@@ -561,7 +562,7 @@ typedef struct _message
t_clock *m_clock; t_clock *m_clock;
} t_message; } t_message;
static t_class *messresponder_class; t_class *messresponder_class;
static void messresponder_bang(t_messresponder *x) static void messresponder_bang(t_messresponder *x)
{ {
...@@ -596,13 +597,17 @@ static void messresponder_anything(t_messresponder *x, ...@@ -596,13 +597,17 @@ static void messresponder_anything(t_messresponder *x,
outlet_anything(x->mr_outlet, s, argc, argv); outlet_anything(x->mr_outlet, s, argc, argv);
} }
/* get the glist cached in a message responder */
t_glist *messresponder_getglist(t_pd *x)
{
return ((t_messresponder *)x)->mr_glist;
}
static void message_bang(t_message *x) static void message_bang(t_message *x)
{ {
/* we do canvas_setcurrent/unsetcurrent to substitute canvas /* we do canvas_setcurrent/unsetcurrent to substitute canvas
instance number for $0 */ instance number for $0 */
canvas_setcurrent((t_canvas *)x->m_glist);
binbuf_eval(x->m_text.te_binbuf, &x->m_messresponder.mr_pd, 0, 0); binbuf_eval(x->m_text.te_binbuf, &x->m_messresponder.mr_pd, 0, 0);
canvas_unsetcurrent((t_canvas *)x->m_glist);
} }
static void message_float(t_message *x, t_float f) static void message_float(t_message *x, t_float f)
...@@ -611,9 +616,7 @@ static void message_float(t_message *x, t_float f) ...@@ -611,9 +616,7 @@ static void message_float(t_message *x, t_float f)
SETFLOAT(&at, f); SETFLOAT(&at, f);
/* we do canvas_setcurrent/unsetcurrent to substitute canvas /* we do canvas_setcurrent/unsetcurrent to substitute canvas
instance number for $0 */ instance number for $0 */
canvas_setcurrent((t_canvas *)x->m_glist);
binbuf_eval(x->m_text.te_binbuf, &x->m_messresponder.mr_pd, 1, &at); binbuf_eval(x->m_text.te_binbuf, &x->m_messresponder.mr_pd, 1, &at);
canvas_unsetcurrent((t_canvas *)x->m_glist);
} }
static void message_symbol(t_message *x, t_symbol *s) static void message_symbol(t_message *x, t_symbol *s)
...@@ -622,9 +625,7 @@ static void message_symbol(t_message *x, t_symbol *s) ...@@ -622,9 +625,7 @@ static void message_symbol(t_message *x, t_symbol *s)
SETSYMBOL(&at, s); SETSYMBOL(&at, s);
/* we do canvas_setcurrent/unsetcurrent to substitute canvas /* we do canvas_setcurrent/unsetcurrent to substitute canvas
instance number for $0 */ instance number for $0 */
canvas_setcurrent((t_canvas *)x->m_glist);
binbuf_eval(x->m_text.te_binbuf, &x->m_messresponder.mr_pd, 1, &at); binbuf_eval(x->m_text.te_binbuf, &x->m_messresponder.mr_pd, 1, &at);
canvas_unsetcurrent((t_canvas *)x->m_glist);
} }
static void message_blob(t_message *x, t_blob *st) static void message_blob(t_message *x, t_blob *st)
...@@ -633,9 +634,7 @@ static void message_blob(t_message *x, t_blob *st) ...@@ -633,9 +634,7 @@ static void message_blob(t_message *x, t_blob *st)
SETBLOB(&at, st); SETBLOB(&at, st);
/* we do canvas_setcurrent/unsetcurrent to substitute canvas /* we do canvas_setcurrent/unsetcurrent to substitute canvas
instance number for $0 */ instance number for $0 */
canvas_setcurrent((t_canvas *)x->m_glist);
binbuf_eval(x->m_text.te_binbuf, &x->m_messresponder.mr_pd, 1, &at); binbuf_eval(x->m_text.te_binbuf, &x->m_messresponder.mr_pd, 1, &at);
canvas_unsetcurrent((t_canvas *)x->m_glist);
} }
static void message_list(t_message *x, t_symbol *s, int argc, t_atom *argv) static void message_list(t_message *x, t_symbol *s, int argc, t_atom *argv)
...@@ -645,9 +644,7 @@ static void message_list(t_message *x, t_symbol *s, int argc, t_atom *argv) ...@@ -645,9 +644,7 @@ static void message_list(t_message *x, t_symbol *s, int argc, t_atom *argv)
// but will this break anything? // but will this break anything?
/* we do canvas_setcurrent/unsetcurrent to substitute canvas /* we do canvas_setcurrent/unsetcurrent to substitute canvas
instance number for $0 */ instance number for $0 */
canvas_setcurrent((t_canvas *)x->m_glist);
binbuf_eval(x->m_text.te_binbuf, &x->m_messresponder.mr_pd, argc, argv); binbuf_eval(x->m_text.te_binbuf, &x->m_messresponder.mr_pd, argc, argv);
canvas_unsetcurrent(x->m_glist);
} }
static void message_set(t_message *x, t_symbol *s, int argc, t_atom *argv) static void message_set(t_message *x, t_symbol *s, int argc, t_atom *argv)
...@@ -779,6 +776,7 @@ void canvas_msg(t_glist *gl, t_symbol *s, int argc, t_atom *argv) ...@@ -779,6 +776,7 @@ void canvas_msg(t_glist *gl, t_symbol *s, int argc, t_atom *argv)
t_message *x = (t_message *)pd_new(message_class); t_message *x = (t_message *)pd_new(message_class);
x->m_messresponder.mr_pd = messresponder_class; x->m_messresponder.mr_pd = messresponder_class;
x->m_messresponder.mr_outlet = outlet_new(&x->m_text, &s_float); x->m_messresponder.mr_outlet = outlet_new(&x->m_text, &s_float);
x->m_messresponder.mr_glist = gl;
x->m_text.te_width = 0; /* don't know it yet. */ x->m_text.te_width = 0; /* don't know it yet. */
x->m_text.te_type = T_MESSAGE; x->m_text.te_type = T_MESSAGE;
x->m_text.te_iemgui = 0; x->m_text.te_iemgui = 0;
......
...@@ -549,7 +549,7 @@ int binbuf_resize(t_binbuf *x, int newsize) ...@@ -549,7 +549,7 @@ int binbuf_resize(t_binbuf *x, int newsize)
return (new != 0); return (new != 0);
} }
int canvas_getdollarzero( void); int canvas_getdollarzero(t_pd *x);
/* JMZ: /* JMZ:
* s points to the first character after the $ * s points to the first character after the $
...@@ -602,7 +602,8 @@ int binbuf_expanddollsym(char*s, char*buf,t_atom dollar0, int ac, t_atom *av, ...@@ -602,7 +602,8 @@ int binbuf_expanddollsym(char*s, char*buf,t_atom dollar0, int ac, t_atom *av,
/* LATER remove the dependence on the current canvas for $0; should be another /* LATER remove the dependence on the current canvas for $0; should be another
argument. */ argument. */
t_symbol *binbuf_realizedollsym(t_symbol *s, int ac, t_atom *av, int tonew) static t_symbol *binbuf_dorealizedollsym(t_pd *target, t_symbol *s, int ac,
t_atom *av, int tonew)
{ {
char buf[MAXPDSTRING]; char buf[MAXPDSTRING];
char buf2[MAXPDSTRING]; char buf2[MAXPDSTRING];
...@@ -610,7 +611,7 @@ t_symbol *binbuf_realizedollsym(t_symbol *s, int ac, t_atom *av, int tonew) ...@@ -610,7 +611,7 @@ t_symbol *binbuf_realizedollsym(t_symbol *s, int ac, t_atom *av, int tonew)
char*substr; char*substr;
int next=0, i=MAXPDSTRING; int next=0, i=MAXPDSTRING;
t_atom dollarnull; t_atom dollarnull;
SETFLOAT(&dollarnull, canvas_getdollarzero()); SETFLOAT(&dollarnull, canvas_getdollarzero(target));
while(i--)buf2[i]=0; while(i--)buf2[i]=0;
#if 1 #if 1
...@@ -637,7 +638,7 @@ t_symbol *binbuf_realizedollsym(t_symbol *s, int ac, t_atom *av, int tonew) ...@@ -637,7 +638,7 @@ t_symbol *binbuf_realizedollsym(t_symbol *s, int ac, t_atom *av, int tonew)
* JMZ: i am not sure what this means, so i might have broken it * JMZ: i am not sure what this means, so i might have broken it
* it seems like that if "tonew" is set and the $arg cannot be expanded * it seems like that if "tonew" is set and the $arg cannot be expanded
* (or the dollarsym is in reality a A_DOLLAR) * (or the dollarsym is in reality a A_DOLLAR)
* 0 is returned from binbuf_realizedollsym * 0 is returned from binbuf_dorealizedollsym
* this happens, when expanding in a message-box, but does not happen * this happens, when expanding in a message-box, but does not happen
* when the A_DOLLSYM is the name of a subpatch * when the A_DOLLSYM is the name of a subpatch
*/ */
...@@ -664,6 +665,11 @@ done: ...@@ -664,6 +665,11 @@ done:
return (gensym(buf2)); return (gensym(buf2));
} }
t_symbol *binbuf_realizedollsym(t_symbol *s, int ac, t_atom *av, int tonew)
{
return binbuf_dorealizedollsym(0, s, ac, av, tonew);
}
#define SMALLMSG 5 #define SMALLMSG 5
#define HUGEMSG 1000 #define HUGEMSG 1000
#ifdef MSW #ifdef MSW
...@@ -681,12 +687,28 @@ done: ...@@ -681,12 +687,28 @@ done:
#define ATOMS_FREEA(x, n) (freebytes((x), (n) * sizeof(t_atom))) #define ATOMS_FREEA(x, n) (freebytes((x), (n) * sizeof(t_atom)))
#endif #endif
t_pd *pd_mess_from_responder(t_pd *x);
static void binbuf_error(t_pd *x, const char *fmt, ...)
{
char buf[MAXPDSTRING];
va_list ap;
va_start(ap, fmt);
vsnprintf(buf, MAXPDSTRING-1, fmt, ap);
va_end(ap);
if (x)
pd_error(pd_mess_from_responder(x), buf);
else
error(buf);
}
void binbuf_eval(t_binbuf *x, t_pd *target, int argc, t_atom *argv) void binbuf_eval(t_binbuf *x, t_pd *target, int argc, t_atom *argv)
{ {
t_atom smallstack[SMALLMSG], *mstack, *msp; t_atom smallstack[SMALLMSG], *mstack, *msp;
t_atom *at = x->b_vec; t_atom *at = x->b_vec;
int ac = x->b_n; int ac = x->b_n;
int nargs, maxnargs = 0; int nargs, maxnargs = 0;
/* initial target for referencing $0 in msg boxes after a semicolon */
t_pd * init_target = target;
//first we need to check if the list of arguments has $@ //first we need to check if the list of arguments has $@
//fprintf(stderr,"=========\nbinbuf_eval argc:%d ac:%d\n", argc, (int)ac); //fprintf(stderr,"=========\nbinbuf_eval argc:%d ac:%d\n", argc, (int)ac);
...@@ -769,13 +791,18 @@ void binbuf_eval(t_binbuf *x, t_pd *target, int argc, t_atom *argv) ...@@ -769,13 +791,18 @@ void binbuf_eval(t_binbuf *x, t_pd *target, int argc, t_atom *argv)
/* would it make sense to consider $@ here? */ /* would it make sense to consider $@ here? */
if (at->a_w.w_index <= 0 || at->a_w.w_index > argc) if (at->a_w.w_index <= 0 || at->a_w.w_index > argc)
{ {
error("$%d: not enough arguments supplied", binbuf_error(init_target,
at->a_w.w_index); "$%d: %s",
at->a_w.w_index,
(at->a_w.w_index == 0 ?
"symbol needed as message destination" :
"not enough arguments supplied"));
goto cleanup; goto cleanup;
} }
else if (argv[at->a_w.w_index-1].a_type != A_SYMBOL) else if (argv[at->a_w.w_index-1].a_type != A_SYMBOL)
{ {
error("$%d: symbol needed as message destination", binbuf_error(init_target,
"$%d: symbol needed as message destination",
at->a_w.w_index); at->a_w.w_index);
goto cleanup; goto cleanup;
} }
...@@ -783,10 +810,11 @@ void binbuf_eval(t_binbuf *x, t_pd *target, int argc, t_atom *argv) ...@@ -783,10 +810,11 @@ void binbuf_eval(t_binbuf *x, t_pd *target, int argc, t_atom *argv)
} }
else if (at->a_type == A_DOLLSYM) else if (at->a_type == A_DOLLSYM)
{ {
if (!(s = binbuf_realizedollsym(at->a_w.w_symbol, if (!(s = binbuf_dorealizedollsym(init_target, at->a_w.w_symbol,
argc, argv, 0))) argc, argv, 0)))
{ {
error("$%s: not enough arguments supplied", binbuf_error(init_target,
"$%s: not enough arguments supplied",
at->a_w.w_symbol->s_name); at->a_w.w_symbol->s_name);
goto cleanup; goto cleanup;
} }
...@@ -794,7 +822,8 @@ void binbuf_eval(t_binbuf *x, t_pd *target, int argc, t_atom *argv) ...@@ -794,7 +822,8 @@ void binbuf_eval(t_binbuf *x, t_pd *target, int argc, t_atom *argv)
else s = atom_getsymbol(at); else s = atom_getsymbol(at);
if (!(target = s->s_thing)) if (!(target = s->s_thing))
{ {
error("%s: no such object", s->s_name); binbuf_error(init_target,
"%s: no such object", s->s_name);
cleanup: cleanup:
do at++, ac--; do at++, ac--;
while (ac && at->a_type != A_SEMI); while (ac && at->a_type != A_SEMI);
...@@ -865,25 +894,27 @@ void binbuf_eval(t_binbuf *x, t_pd *target, int argc, t_atom *argv) ...@@ -865,25 +894,27 @@ void binbuf_eval(t_binbuf *x, t_pd *target, int argc, t_atom *argv)
else if (at->a_w.w_index > 0 && at->a_w.w_index <= argc) else if (at->a_w.w_index > 0 && at->a_w.w_index <= argc)
*msp = argv[at->a_w.w_index-1]; *msp = argv[at->a_w.w_index-1];
else if (at->a_w.w_index == 0) else if (at->a_w.w_index == 0)
SETFLOAT(msp, canvas_getdollarzero()); SETFLOAT(msp, canvas_getdollarzero(init_target));
else else
{ {
if (target == &pd_objectmaker) if (target == &pd_objectmaker)
SETFLOAT(msp, 0); SETFLOAT(msp, 0);
else else
{ {
error("$%d: argument number out of range", binbuf_error(init_target,
"$%d: argument number out of range",
at->a_w.w_index); at->a_w.w_index);
SETFLOAT(msp, 0); SETFLOAT(msp, 0);
} }
} }
break; break;
case A_DOLLSYM: case A_DOLLSYM:
s9 = binbuf_realizedollsym(at->a_w.w_symbol, argc, argv, s9 = binbuf_dorealizedollsym(init_target, at->a_w.w_symbol,
target == &pd_objectmaker); argc, argv, target == &pd_objectmaker);
if (!s9) if (!s9)
{ {
error("%s: argument number out of range", binbuf_error(init_target,
"%s: argument number out of range",
at->a_w.w_symbol->s_name); at->a_w.w_symbol->s_name);
SETSYMBOL(msp, at->a_w.w_symbol); SETSYMBOL(msp, at->a_w.w_symbol);
} }
......
...@@ -1355,7 +1355,7 @@ static void text_sequence_doit(t_text_sequence *x, int argc, t_atom *argv) ...@@ -1355,7 +1355,7 @@ static void text_sequence_doit(t_text_sequence *x, int argc, t_atom *argv)
if (i >= n) if (i >= n)
i = 0x7fffffff; i = 0x7fffffff;
x->x_onset = i; x->x_onset = i;
/* generate output list, realizing dolar sign atoms. Allocate one /* generate output list, realizing dollar sign atoms. Allocate one
extra atom in case we want to prepend a symbol later */ extra atom in case we want to prepend a symbol later */
ATOMS_ALLOCA(outvec, nfield+1); ATOMS_ALLOCA(outvec, nfield+1);
for (i = 0, ap = vec+onset; i < nfield; i++, ap++) for (i = 0, ap = vec+onset; i < nfield; i++, ap++)
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment