diff --git a/glib/gstrfuncs.c b/glib/gstrfuncs.c
index 8e4b226..df6145b 100644
--- a/glib/gstrfuncs.c
+++ b/glib/gstrfuncs.c
@@ -3244,6 +3244,107 @@ g_dngettext (const gchar *domain,
   return dngettext (domain, msgid, msgid_plural, n);
 }
 
+/*********** GRefString ****************/
+
+G_LOCK_DEFINE_STATIC (interned_ref_strs);
+static GHashTable *interned_ref_strs = NULL;
+
+static GRefString *
+g_ref_string_new_internal (const char *string, int start_count)
+{
+  char *res;
+  volatile gint *count;
+  gsize len;
+
+  len = strlen (string);
+  res = g_malloc (sizeof (gint) + len + 1);
+  count = (volatile gint *)res;
+  *count = start_count;
+  res += sizeof(gint);
+  memcpy (res, string, len + 1);
+  return res;
+}
+
+GRefString *
+g_ref_string_new (const char *string)
+{
+  if (string == NULL)
+    return NULL;
+
+  return g_ref_string_new_internal (string, 1);
+}
+
+GRefString *
+g_ref_string_intern (const char *string)
+{
+  GRefString * res;
+
+  if (string == NULL)
+    return NULL;
+
+  G_LOCK (interned_ref_strs);
+
+  if (interned_ref_strs == NULL)
+    interned_ref_strs = g_hash_table_new (g_str_hash, g_str_equal);
+
+  res = g_hash_table_lookup (interned_ref_strs, string);
+  if (res != NULL)
+    g_ref_string_ref (res);
+  else
+    {
+      res = g_ref_string_new_internal (string, 0x40000001U);
+      g_hash_table_insert (interned_ref_strs, res, res);
+    }
+
+  G_UNLOCK (interned_ref_strs);
+
+  return res;
+}
+
+GRefString *
+g_ref_string_ref (GRefString * str)
+{
+  volatile gint *count;
+
+  count = (volatile gint *)((char *)str - sizeof (gint));
+  g_atomic_int_add (count, 1);
+
+  return str;
+}
+
+void
+g_ref_string_unref (GRefString *str)
+{
+  volatile gint *count;
+  gint old_ref;
+
+  if (str == NULL)
+    return;
+
+  count = (volatile gint *)((char *)str - sizeof (gint));
+
+ retry_atomic_decrement:
+
+  old_ref = g_atomic_int_get (count);
+
+  if (old_ref == 1)
+    g_free ((char *)count);
+  else if (old_ref == 0x40000001)
+    {
+      G_LOCK (interned_ref_strs);
+
+      /* Need to recheck after taking lock to avoid races with _intern() */
+      if (g_atomic_int_exchange_and_add (count, -1) == 0x40000001)
+	{
+	  g_hash_table_remove (interned_ref_strs, (char *)str);
+	  g_free ((char *)count);
+	}
+
+      G_UNLOCK (interned_ref_strs);
+    } else if (!g_atomic_int_compare_and_exchange (count,
+						   old_ref, old_ref - 1))
+    goto retry_atomic_decrement;
+}
 
 #define __G_STRFUNCS_C__
 #include "galiasdef.c"
diff --git a/glib/gstrfuncs.h b/glib/gstrfuncs.h
index 534f26e..0d4839e 100644
--- a/glib/gstrfuncs.h
+++ b/glib/gstrfuncs.h
@@ -262,6 +262,17 @@ G_CONST_RETURN gchar *g_dpgettext2     (const gchar *domain,
                                         const gchar *context,
                                         const gchar *msgid) G_GNUC_FORMAT(3);
 
+
+typedef struct _GRefString GRefString;
+
+GRefString *g_ref_string_new    (const char *string);
+GRefString *g_ref_string_intern (const char *string);
+GRefString *g_ref_string_ref    (GRefString *str);
+void        g_ref_string_unref  (GRefString *str);
+
+#define g_ref_string_peek(__str) ((const char *)(__str))
+
+
 G_END_DECLS
 
 #endif /* __G_STRFUNCS_H__ */
