Re: Signal handlers: parameter names



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]