GValue allocation schemes (Re: Bug in string GValues?)



On 1 Aug 2001, Anders Carlsson wrote:

> Hello,
> 
> when setting a GValue to a string by using g_value_set_static_string,
> the string is copied when using g_value_copy. This is the function
> that's called when you copy a string:
> 
> static void
> value_copy_string (const GValue *src_value,
> 		   GValue	*dest_value)
> {
>   dest_value->data[0].v_pointer = g_strdup(src_value->data[0].v_pointer);
> }
> 
> Shouldn't this function honor the G_VALUE_NOCOPY_CONTENTS flag?

nope it shouldn't.

the short answer is:
static!=static, when copying a value we don't know whether its contents
are really C-static and const, i.e. living in a persistent const-data
section of a program (or are dynamically allocated with alloc-only
semantics and guaranteed to be non-mutatable).

the long answer is:
(writing this down here since irc, we haven't given a public explaination
for GValue allocation schemes yet, and for reference upon future FAQs)

GValue ideally would deal with at least 6 different
allocation/mutation schemes for its contents:

allocation/reference pattern for: storage    | g_copy_value
1) const static persistent	[ no-copy    | no-copy ]
2) const static limted          [ no-copy    | copy ]
3) const temporary		[ copy       | copy ]
4) mutatable static persistent	[ no-copy    | copy ]
5) mutatable static limited	[ no-copy    | copy ]
6) mutatable temporary		[ copy       | copy ]

where "persistent" means that the value contents to be set remain
throughout a programs lifetime (e.g. a "static const char *foo;" in main()).

"limited" applies for e.g. a static variable "static char *bar;" that
(potentially) lives in a dynamic module, but for which the GValue owner
can make the guarantee that the GValue's lifetime is limited to the
lifetime of its contents (in other words, he'd unset the GValue before
the module holding "bar" gets unloaded).

"temporary" simply refers to dynamic allocation, e.g.
  char *x = g_strdup_printf ("huhu%u", 21);
  g_value_set_string (value, x);
  g_free (x);

now GValue doesn't actually take notion of its contents being constant,
which is e.g. why g_value_get_object() returns GObject* types and not
const GObject* (actually it returns gpointer, but that's just C convenience).
the reason i listed const distinctively above is, that even for
  main() { static char *baz = "x"; }
which is persistent and mutatable, g_value_copy() would have to copy the
contents, or the contents of the copied values would change with alterations
of the original value's contents (and that would be copy-by-reference,
not copy-by-value semantics).
in practice, g_value_copy() has copy-by-reference semantics for objects,
but should guarantee copy-by-value semantics for things like floats, ints
or strings.
and even for const static limited contents (2), g_value_copy() nees to
copy the contents, since the destination value doesn't necessarily give
the same limited GValue lifetime guarantee as the source value does.

now, say we'd support all of the above allocation schemes for GValue,
that would bloat the GValue setters/getters by an order of nearly six,
greatly increase complexity and just get us the slight benefit of
avoiding unecessary copies for (1).

instead, the API we now have effectively follows:
- GValue contents are never constant (gets rid of (1), (2) and (3))
- GValue contents are set either from temporary or static limited
  sources (combines (4) with (5))

which gets us:
(3,6)     g_value_set_string            (GValue*, const gchar *string);
(1,2,4,5) g_value_set_static_string     (GValue*, const gchar *string);
(1,2,3,4,5,6) G_CONST_RETURN gchar* g_value_get_string (GValue*);
(1,2,3,4,5,6) g_value_copy (src,dest) { src = strdup (dest); }

with the acceptable disadvantages of:
- g_value_set_static_string() accepting const strings, but internally casts
  them into mutatable strings, strictly speaking, a violation of (1,2)
- g_value_copy() being slightly inefficient for (1)

> 
> //andersca
> andersca gnu org
> 

---
ciaoTJ






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