Re: Reserving quarks



On 19 Aug 2000, Espen S Johnsen wrote:

> I am currently updating (actually rewriting) my Common Lisp bindings to
> GTK for version 1.3 and was just looking into moving the user data stuff
> from GtkObject to GObject when the following issue came up.
> 
> In Lisp one usually do not use strings as data keys but rather symbols
> or other objects compareable with eq. So in the current implementation,
> names of symbols (which are strings) used as keys get passed to
> gtk_object_get/set_data.  In addition to the lack of similar functions
> for GObject, this has two major problems; it limits the keys to symbols
> and two different symbols may have the same name (and I won't even
> mention the memory overhead).
> 
> As a solution I was thinking of doing my own object to quark mapping. To
> do this it would be necessary to reserve quarks from glib for this
> use. Something like the function in the follwing patch would have to be
> added to glib. Is that possible?

i don't think inflating quark ids is the best solution here.
especially if you use several distinct but equally named symbols,
you probably have to have some other mechanism to do symbol->quark
lookups right?
on a broader scale, there are other occasions where people would
like to set integer-keyed data on objects, with those keys not
necessarily being quarks, e.g. because they are created dynamially.
inflating quark ids and internally allocating an extra NULL pointer
just to "alias" an integer to a blind quark seems like a waste to me,
and more importantly the constrain of quark<->string_content being
a 1:1 relation is violated.
instead you might want to install your own lookup table for data
obejcts through a CLisp specific data item, either based on the
current GData, e.g.:

static GQuark clisp_data = g_quark_from_static_string ("clisp-gdata");

static void
gdata_destroy (gpointer data)
{
  GData **gdata_p = data;
  
  g_datalist_clear (gdata_p);
  g_free (gdata_p);
}

void
g_object_set_clisp_data_full (GObject *o, guint id, gpointer data, GDestroyNotify df)
{
  GData **gdata_p = g_object_get_qdata (o, clisp_data);
  
  if (!gdata_p)
    {
      gdata_p = g_new (GData*, 1);
      g_datalist_init (gdata_p);
      g_object_set_qdata_full (o, clisp_data, gdata_p, gdata_destroy);
    }
  g_datalist_id_set_data_full (gdata_p, id, data, df);
}

gpointer
g_object_get_clisp_data (GObject *o, guint id)
{
  GData **gdata_p = g_object_get_qdata (o, clisp_data);
  
  if (gdata_p)
    return g_datalist_id_get_data (gdata_p, id);
  
  return NULL;
}

(yes, you could spare that extra g_new (GData*, 1), but that would involve
 resetting the GData* pointer for every g_object_set_clisp_data_full() call
 through g_object_set_qdata_full() and make things pretty inefficient)


the other solution, noteworthy because you may not necessarily need a
GDestroyNotify function for your clisp data is to use a sorted array that
allowes for binary lookups of arbitrarily sized data items. glib will
soon come with such a thing, because the new signal and type code needs
that. if you want to go for that solution, i can supply you with my initial
implementation in private email.

(on another note, GData lookups are currently O(n_items). that'll change
to O(log2(n_items)) for 2.0, but only after the new signal code is working
and the binary searchable sorted array code is already there ;)

---
ciaoTJ






[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]