Re: Signal handlers: parameter names
- From: Tim Janik <timj gtk org>
- To: "Padraig O'Briain" <Padraig Obriain Sun COM>
- Cc: jmargaglione yahoo com, cssl geocities com, Gtk+ Developers <gtk-devel-list gnome org>
- Subject: Re: Signal handlers: parameter names
- Date: Tue, 13 Mar 2001 00:28:38 +0100 (CET)
On Mon, 12 Mar 2001, Padraig O'Briain wrote:
> > John Margaglione wrote:
> > > I'm not talking about invoking signals, I'm talking about creating a
> > > dialog box to connect signals. In Glade right now you can select a
> > > signal by choosing from a list of available signals from a listbox.
> > > When you choose one of the signals and generate the source code, Glade
> > > has to do a lookup on the names of the parameters to the signal. These
> > > have to be stored as static arrays in the Glade source code. If a new
> > > signal is added, or the names of the parameters are changed, Glade has
> > > to be updated. Using my suggestion there is no rework of Glade
> > > necessary.
> > Then, why don't you use an XML file that describes them ? So :
> > 0) no runtime penalty, except at startup (scan the XML file once and
> > build tables in memory)
>
> Startup costs are not insignificant. Perception of performance is probably more
> important than the results of any benchmark you run and perception of
> performance is very heavily influenced by startup time.
>
i see. that is, if we could get the startup time required for builders that
will use text files to store signal arguments down to a reasonable
minimum, this would be viable?
attached is a sample parser for the syntax i suggested, timing it on a 550mhz
machine with 1000 signal signatures ala:
GtkCList::extend_selection (clist, scroll_type, position, auto_start_selection) return foobar;
i'm getting:
parsed 1000 signal signatures
real 0m0.090s
user 0m0.090s
sys 0m0.000s
do you think that is an acceptable performance hit for your user base?
---
ciaoTJ
#include <glib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
typedef struct {
gchar *type_name;
gchar *signal_name;
GSList *args; /* of type gchar* */
gchar *return_name;
} Signature;
static GHashTable *signature_ht = NULL;
static guint n_signals = 0;
static guint
signature_hash (gconstpointer data)
{
const Signature *ssig = data;
return g_str_hash (ssig->type_name) ^ g_str_hash (ssig->signal_name);
}
static gint
signatures_equal (gconstpointer data1,
gconstpointer data2)
{
const Signature *ssig1 = data1;
const Signature *ssig2 = data2;
return (strcmp (ssig1->type_name, ssig2->type_name) == 0 &&
strcmp (ssig1->signal_name, ssig2->signal_name) == 0);
}
static void
free_signature (Signature *ssig)
{
GSList *node;
for (node = ssig->args; node; node = node->next)
g_free (node->data);
g_slist_free (ssig->args);
g_free (ssig->type_name);
g_free (ssig->signal_name);
g_free (ssig->return_name);
g_free (ssig);
}
static guint
parse_signature (GScanner *scanner,
Signature *ssig)
{
/* parse signal spec, e.g.: GtkWidget::expose_event (widget, expose_event) return handled; */
g_scanner_get_next_token (scanner);
if (scanner->token != G_TOKEN_IDENTIFIER)
return G_TOKEN_IDENTIFIER;
ssig->type_name = g_strdup (scanner->value.v_string);
if (g_scanner_get_next_token (scanner) != ':' ||
g_scanner_get_next_token (scanner) != ':')
return ':';
g_scanner_get_next_token (scanner);
if (scanner->token != G_TOKEN_IDENTIFIER)
return G_TOKEN_IDENTIFIER;
ssig->signal_name = g_strdup (scanner->value.v_string);
if (g_scanner_get_next_token (scanner) != '(')
return '(';
do
{
g_scanner_get_next_token (scanner);
if (scanner->token != G_TOKEN_IDENTIFIER)
return G_TOKEN_IDENTIFIER;
ssig->args = g_slist_prepend (ssig->args, g_strdup (scanner->value.v_string));
if (g_scanner_peek_next_token (scanner) == ',')
{
g_scanner_get_next_token (scanner); /* ',' */
continue;
}
else
break;
}
while (1);
if (g_scanner_get_next_token (scanner) != ')')
return ')';
/* feature optional return <name> phrase */
if (g_scanner_peek_next_token (scanner) == G_TOKEN_IDENTIFIER &&
strcmp (scanner->next_value.v_string, "return") == 0)
{
g_scanner_get_next_token (scanner);
g_scanner_get_next_token (scanner);
if (scanner->token != G_TOKEN_IDENTIFIER)
return G_TOKEN_IDENTIFIER;
ssig->return_name = g_strdup (scanner->value.v_string);
}
if (g_scanner_get_next_token (scanner) != ';')
return ';';
return G_TOKEN_NONE;
}
static void
parse_file (const gchar *file_name)
{
GScanner *scanner;
guint token;
gint fd;
g_return_if_fail (file_name != NULL);
fd = open (file_name, O_RDONLY);
if (fd < 0)
return;
scanner = g_scanner_new (NULL);
scanner->input_name = file_name;
g_scanner_input_file (scanner, fd);
while (g_scanner_peek_next_token (scanner) != G_TOKEN_EOF)
{
Signature *ssig = g_new0 (Signature, 1);
token = parse_signature (scanner, ssig);
if (token == G_TOKEN_NONE)
{
ssig->args = g_slist_reverse (ssig->args);
g_hash_table_insert (signature_ht, ssig, ssig);
n_signals++;
}
else
{
free_signature (ssig);
g_scanner_unexp_token (scanner, token, NULL, NULL, NULL, NULL, TRUE);
break;
}
}
close (fd);
g_scanner_destroy (scanner);
}
int
main (int argc,
char *argv[])
{
guint i;
signature_ht = g_hash_table_new (signature_hash, signatures_equal);
for (i = 1; i < argc; i++)
parse_file (argv[i]);
g_print ("parsed %u signal signatures\n", n_signals);
return 0;
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]