GMainContext useful in implementing some additional styles of main loop
authorElliot Lee <sopwith@src.gnome.org>
Tue, 12 Dec 2000 19:34:41 +0000 (19:34 +0000)
committerElliot Lee <sopwith@src.gnome.org>
Tue, 12 Dec 2000 19:34:41 +0000 (19:34 +0000)
* gmain.c, gmain.h (g_main_context_new, g_main_context_destroy): GMainContext useful
in implementing some additional styles of main loop usage.  To do this, however, Joe
Hacker needs to be able to create/destroy GMainContext's at will. This is just an
export of existing functionality, rather than new functionality.

They are listed in the "Low level functions for implementing custom main loops"
section of the header file, to avoid confusing people.

* gobject/Makefile.am:
  . You have to 'touch oldest-source-stamp' if you want to avoid having
  the Makefile constantly rebuild itself.
  . Fix marshaller generation rules to work with srcdir != builddir
    (there were issues with trying to run "./glib-genmarshal", etc.)

14 files changed:
ChangeLog
ChangeLog.pre-2-0
ChangeLog.pre-2-10
ChangeLog.pre-2-12
ChangeLog.pre-2-2
ChangeLog.pre-2-4
ChangeLog.pre-2-6
ChangeLog.pre-2-8
glib/gmain.c
glib/gmain.h
gmain.c
gmain.h
gobject/ChangeLog
gobject/Makefile.am

index 5b831371203c0840e5d910515ee75d3d7ed60820..aefd74667736f6a4b524ae24909dbb733dac5ab0 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,14 @@
+2000-12-12  Elliot Lee  <sopwith@redhat.com>
+
+       * gmain.c, gmain.h (g_main_context_new, g_main_context_destroy):
+       GMainContext useful in implementing some additional styles of
+       main loop usage.  To do this, however, Joe Hacker needs to be able
+       to create/destroy GMainContext's at will. This is just an export
+       of existing functionality, rather than any new functionality.
+
+       They are listed in the "Low level functions for implementing custom
+       main loops" section of the header file, to avoid confusing people.
+
 Sun Dec 10 10:47:11 2000  Owen Taylor  <otaylor@redhat.com>
 
        * gmain.c (g_source_destroy_internal): Remove pollfds
index 5b831371203c0840e5d910515ee75d3d7ed60820..aefd74667736f6a4b524ae24909dbb733dac5ab0 100644 (file)
@@ -1,3 +1,14 @@
+2000-12-12  Elliot Lee  <sopwith@redhat.com>
+
+       * gmain.c, gmain.h (g_main_context_new, g_main_context_destroy):
+       GMainContext useful in implementing some additional styles of
+       main loop usage.  To do this, however, Joe Hacker needs to be able
+       to create/destroy GMainContext's at will. This is just an export
+       of existing functionality, rather than any new functionality.
+
+       They are listed in the "Low level functions for implementing custom
+       main loops" section of the header file, to avoid confusing people.
+
 Sun Dec 10 10:47:11 2000  Owen Taylor  <otaylor@redhat.com>
 
        * gmain.c (g_source_destroy_internal): Remove pollfds
index 5b831371203c0840e5d910515ee75d3d7ed60820..aefd74667736f6a4b524ae24909dbb733dac5ab0 100644 (file)
@@ -1,3 +1,14 @@
+2000-12-12  Elliot Lee  <sopwith@redhat.com>
+
+       * gmain.c, gmain.h (g_main_context_new, g_main_context_destroy):
+       GMainContext useful in implementing some additional styles of
+       main loop usage.  To do this, however, Joe Hacker needs to be able
+       to create/destroy GMainContext's at will. This is just an export
+       of existing functionality, rather than any new functionality.
+
+       They are listed in the "Low level functions for implementing custom
+       main loops" section of the header file, to avoid confusing people.
+
 Sun Dec 10 10:47:11 2000  Owen Taylor  <otaylor@redhat.com>
 
        * gmain.c (g_source_destroy_internal): Remove pollfds
index 5b831371203c0840e5d910515ee75d3d7ed60820..aefd74667736f6a4b524ae24909dbb733dac5ab0 100644 (file)
@@ -1,3 +1,14 @@
+2000-12-12  Elliot Lee  <sopwith@redhat.com>
+
+       * gmain.c, gmain.h (g_main_context_new, g_main_context_destroy):
+       GMainContext useful in implementing some additional styles of
+       main loop usage.  To do this, however, Joe Hacker needs to be able
+       to create/destroy GMainContext's at will. This is just an export
+       of existing functionality, rather than any new functionality.
+
+       They are listed in the "Low level functions for implementing custom
+       main loops" section of the header file, to avoid confusing people.
+
 Sun Dec 10 10:47:11 2000  Owen Taylor  <otaylor@redhat.com>
 
        * gmain.c (g_source_destroy_internal): Remove pollfds
index 5b831371203c0840e5d910515ee75d3d7ed60820..aefd74667736f6a4b524ae24909dbb733dac5ab0 100644 (file)
@@ -1,3 +1,14 @@
+2000-12-12  Elliot Lee  <sopwith@redhat.com>
+
+       * gmain.c, gmain.h (g_main_context_new, g_main_context_destroy):
+       GMainContext useful in implementing some additional styles of
+       main loop usage.  To do this, however, Joe Hacker needs to be able
+       to create/destroy GMainContext's at will. This is just an export
+       of existing functionality, rather than any new functionality.
+
+       They are listed in the "Low level functions for implementing custom
+       main loops" section of the header file, to avoid confusing people.
+
 Sun Dec 10 10:47:11 2000  Owen Taylor  <otaylor@redhat.com>
 
        * gmain.c (g_source_destroy_internal): Remove pollfds
index 5b831371203c0840e5d910515ee75d3d7ed60820..aefd74667736f6a4b524ae24909dbb733dac5ab0 100644 (file)
@@ -1,3 +1,14 @@
+2000-12-12  Elliot Lee  <sopwith@redhat.com>
+
+       * gmain.c, gmain.h (g_main_context_new, g_main_context_destroy):
+       GMainContext useful in implementing some additional styles of
+       main loop usage.  To do this, however, Joe Hacker needs to be able
+       to create/destroy GMainContext's at will. This is just an export
+       of existing functionality, rather than any new functionality.
+
+       They are listed in the "Low level functions for implementing custom
+       main loops" section of the header file, to avoid confusing people.
+
 Sun Dec 10 10:47:11 2000  Owen Taylor  <otaylor@redhat.com>
 
        * gmain.c (g_source_destroy_internal): Remove pollfds
index 5b831371203c0840e5d910515ee75d3d7ed60820..aefd74667736f6a4b524ae24909dbb733dac5ab0 100644 (file)
@@ -1,3 +1,14 @@
+2000-12-12  Elliot Lee  <sopwith@redhat.com>
+
+       * gmain.c, gmain.h (g_main_context_new, g_main_context_destroy):
+       GMainContext useful in implementing some additional styles of
+       main loop usage.  To do this, however, Joe Hacker needs to be able
+       to create/destroy GMainContext's at will. This is just an export
+       of existing functionality, rather than any new functionality.
+
+       They are listed in the "Low level functions for implementing custom
+       main loops" section of the header file, to avoid confusing people.
+
 Sun Dec 10 10:47:11 2000  Owen Taylor  <otaylor@redhat.com>
 
        * gmain.c (g_source_destroy_internal): Remove pollfds
index 5b831371203c0840e5d910515ee75d3d7ed60820..aefd74667736f6a4b524ae24909dbb733dac5ab0 100644 (file)
@@ -1,3 +1,14 @@
+2000-12-12  Elliot Lee  <sopwith@redhat.com>
+
+       * gmain.c, gmain.h (g_main_context_new, g_main_context_destroy):
+       GMainContext useful in implementing some additional styles of
+       main loop usage.  To do this, however, Joe Hacker needs to be able
+       to create/destroy GMainContext's at will. This is just an export
+       of existing functionality, rather than any new functionality.
+
+       They are listed in the "Low level functions for implementing custom
+       main loops" section of the header file, to avoid confusing people.
+
 Sun Dec 10 10:47:11 2000  Owen Taylor  <otaylor@redhat.com>
 
        * gmain.c (g_source_destroy_internal): Remove pollfds
index f9b26dd1ca9b3bcb6fce9c8e34f0a076dc9563be..d0165daa1a2305263bc1ad49d4332254fddee908 100644 (file)
@@ -485,9 +485,9 @@ g_poll (GPollFD *fds,
 
 #endif /* !HAVE_POLL */
 
-/* Called to clean up when a thread terminates
+/* Called to clean up, usually when a thread terminates
  */
-static void
+void
 g_main_context_destroy (GMainContext *context)
 {
   GSource *source;
@@ -528,80 +528,99 @@ g_main_context_destroy (GMainContext *context)
 }
 
 /**
- * g_main_context_get:
- * @thread: a #GThread
+ * g_main_context_new:
+ * @thread: a #GThread (may be NULL)
  * 
- * Retrieves the main loop context for a particular thread. This
- * will create the main context for the thread if none previously
- * existed. The context will exist until the thread terminates.
+ * This will create a main-loop context. The context will need to be destroyed
+ * via g_main_context_destroy.
  * 
- * Return value: the main loop context for @thread.
+ * Return value: a new main loop context.
  **/
 GMainContext *
-g_main_context_get (GThread *thread)
+g_main_context_new(GThread *thread)
 {
-  static GStaticPrivate private_key = G_STATIC_PRIVATE_INIT;
   GMainContext *context;
 
-  g_return_val_if_fail (thread != NULL, NULL);
-
-  if (g_thread_supported ())
-    context = g_static_private_get_for_thread (&private_key, thread);
-  else
-    context = default_main_context;
-
-  if (!context)
-    {
-      context = g_new0 (GMainContext, 1);
+  context = g_new0 (GMainContext, 1);
 
 #ifdef G_THREADS_ENABLED
-      if (g_thread_supported ())
-       context->mutex = g_mutex_new();
+  if (g_thread_supported ())
+    context->mutex = g_mutex_new();
 
-      context->thread = thread;
+  context->thread = thread;
 #endif
       
-      context->next_id = 1;
+  context->next_id = 1;
       
-      context->source_list = NULL;
+  context->source_list = NULL;
 
 #if HAVE_POLL
-      context->poll_func = (GPollFunc)poll;
+  context->poll_func = (GPollFunc)poll;
 #else
-      context->poll_func = g_poll;
+  context->poll_func = g_poll;
 #endif
 
-      context->cached_poll_array = NULL;
-      context->cached_poll_array_size = 0;
+  context->cached_poll_array = NULL;
+  context->cached_poll_array_size = 0;
       
-      context->pending_dispatches = g_ptr_array_new ();
+  context->pending_dispatches = g_ptr_array_new ();
       
-      context->time_is_current = FALSE;
+  context->time_is_current = FALSE;
 
 #ifdef G_THREADS_ENABLED
-      if (g_thread_supported ())
-       {
+  if (g_thread_supported ())
+    {
 #ifndef G_OS_WIN32
-         if (pipe (context->wake_up_pipe) < 0)
-           g_error ("Cannot create pipe main loop wake-up: %s\n",
-                    g_strerror (errno));
+      if (pipe (context->wake_up_pipe) < 0)
+       g_error ("Cannot create pipe main loop wake-up: %s\n",
+                g_strerror (errno));
          
-         context->wake_up_rec.fd = context->wake_up_pipe[0];
-         context->wake_up_rec.events = G_IO_IN;
-         g_main_context_add_poll_unlocked (context, 0, &context->wake_up_rec);
+      context->wake_up_rec.fd = context->wake_up_pipe[0];
+      context->wake_up_rec.events = G_IO_IN;
+      g_main_context_add_poll_unlocked (context, 0, &context->wake_up_rec);
 #else
-         if ((context->wake_up_semaphore = CreateSemaphore (NULL, 0, 100, NULL)) == NULL)
-           g_error ("Cannot create wake-up semaphore: %s", g_win32_error_message (GetLastError ()));
-         context->wake_up_rec.fd = (gint) context->wake_up_semaphore;
-         context->wake_up_rec.events = G_IO_IN;
+      if ((context->wake_up_semaphore = CreateSemaphore (NULL, 0, 100, NULL)) == NULL)
+       g_error ("Cannot create wake-up semaphore: %s", g_win32_error_message (GetLastError ()));
+      context->wake_up_rec.fd = (gint) context->wake_up_semaphore;
+      context->wake_up_rec.events = G_IO_IN;
 #ifdef G_MAIN_POLL_DEBUG
-         g_print ("wake-up semaphore: %#x\n", (guint) context->wake_up_semaphore);
+      g_print ("wake-up semaphore: %#x\n", (guint) context->wake_up_semaphore);
 #endif
-         g_main_context_add_poll_unlocked (context, 0, &context->wake_up_rec);
+      g_main_context_add_poll_unlocked (context, 0, &context->wake_up_rec);
 #endif
-       }
+    }
 #endif
 
+  return context;
+}
+
+/**
+ * g_main_context_get:
+ * @thread: a #GThread
+ * 
+ * Retrieves the main loop context for a particular thread. This
+ * will create the main context for the thread if none previously
+ * existed. The context will exist until the thread terminates.
+ * 
+ * Return value: the main loop context for @thread.
+ **/
+GMainContext *
+g_main_context_get (GThread *thread)
+{
+  static GStaticPrivate private_key = G_STATIC_PRIVATE_INIT;
+  GMainContext *context;
+
+  g_return_val_if_fail (thread != NULL, NULL);
+
+  if (g_thread_supported ())
+    context = g_static_private_get_for_thread (&private_key, thread);
+  else
+    context = default_main_context;
+
+  if (!context)
+    {
+      context = g_main_context_new (thread);
+
       if (g_thread_supported ())
        g_static_private_set_for_thread (&private_key, thread,
                                         context,
index dd500c6e83c6b7863dadf8eab8a1d4d1f50e72a3..23dd58c5ccc2610e32194fda8be58a80268e44df 100644 (file)
@@ -143,6 +143,9 @@ GSource      *g_main_context_find_source_by_funcs_user_data (GMainContext *conte
 
 /* Low level functions for implementing custom main loops.
  */
+GMainContext *g_main_context_new     (GThread *thread);
+void          g_main_context_destroy (GMainContext *context);
+
 gboolean g_main_context_prepare  (GMainContext *context,
                                  gint         *priority);
 gint     g_main_context_query    (GMainContext *context,
diff --git a/gmain.c b/gmain.c
index f9b26dd1ca9b3bcb6fce9c8e34f0a076dc9563be..d0165daa1a2305263bc1ad49d4332254fddee908 100644 (file)
--- a/gmain.c
+++ b/gmain.c
@@ -485,9 +485,9 @@ g_poll (GPollFD *fds,
 
 #endif /* !HAVE_POLL */
 
-/* Called to clean up when a thread terminates
+/* Called to clean up, usually when a thread terminates
  */
-static void
+void
 g_main_context_destroy (GMainContext *context)
 {
   GSource *source;
@@ -528,80 +528,99 @@ g_main_context_destroy (GMainContext *context)
 }
 
 /**
- * g_main_context_get:
- * @thread: a #GThread
+ * g_main_context_new:
+ * @thread: a #GThread (may be NULL)
  * 
- * Retrieves the main loop context for a particular thread. This
- * will create the main context for the thread if none previously
- * existed. The context will exist until the thread terminates.
+ * This will create a main-loop context. The context will need to be destroyed
+ * via g_main_context_destroy.
  * 
- * Return value: the main loop context for @thread.
+ * Return value: a new main loop context.
  **/
 GMainContext *
-g_main_context_get (GThread *thread)
+g_main_context_new(GThread *thread)
 {
-  static GStaticPrivate private_key = G_STATIC_PRIVATE_INIT;
   GMainContext *context;
 
-  g_return_val_if_fail (thread != NULL, NULL);
-
-  if (g_thread_supported ())
-    context = g_static_private_get_for_thread (&private_key, thread);
-  else
-    context = default_main_context;
-
-  if (!context)
-    {
-      context = g_new0 (GMainContext, 1);
+  context = g_new0 (GMainContext, 1);
 
 #ifdef G_THREADS_ENABLED
-      if (g_thread_supported ())
-       context->mutex = g_mutex_new();
+  if (g_thread_supported ())
+    context->mutex = g_mutex_new();
 
-      context->thread = thread;
+  context->thread = thread;
 #endif
       
-      context->next_id = 1;
+  context->next_id = 1;
       
-      context->source_list = NULL;
+  context->source_list = NULL;
 
 #if HAVE_POLL
-      context->poll_func = (GPollFunc)poll;
+  context->poll_func = (GPollFunc)poll;
 #else
-      context->poll_func = g_poll;
+  context->poll_func = g_poll;
 #endif
 
-      context->cached_poll_array = NULL;
-      context->cached_poll_array_size = 0;
+  context->cached_poll_array = NULL;
+  context->cached_poll_array_size = 0;
       
-      context->pending_dispatches = g_ptr_array_new ();
+  context->pending_dispatches = g_ptr_array_new ();
       
-      context->time_is_current = FALSE;
+  context->time_is_current = FALSE;
 
 #ifdef G_THREADS_ENABLED
-      if (g_thread_supported ())
-       {
+  if (g_thread_supported ())
+    {
 #ifndef G_OS_WIN32
-         if (pipe (context->wake_up_pipe) < 0)
-           g_error ("Cannot create pipe main loop wake-up: %s\n",
-                    g_strerror (errno));
+      if (pipe (context->wake_up_pipe) < 0)
+       g_error ("Cannot create pipe main loop wake-up: %s\n",
+                g_strerror (errno));
          
-         context->wake_up_rec.fd = context->wake_up_pipe[0];
-         context->wake_up_rec.events = G_IO_IN;
-         g_main_context_add_poll_unlocked (context, 0, &context->wake_up_rec);
+      context->wake_up_rec.fd = context->wake_up_pipe[0];
+      context->wake_up_rec.events = G_IO_IN;
+      g_main_context_add_poll_unlocked (context, 0, &context->wake_up_rec);
 #else
-         if ((context->wake_up_semaphore = CreateSemaphore (NULL, 0, 100, NULL)) == NULL)
-           g_error ("Cannot create wake-up semaphore: %s", g_win32_error_message (GetLastError ()));
-         context->wake_up_rec.fd = (gint) context->wake_up_semaphore;
-         context->wake_up_rec.events = G_IO_IN;
+      if ((context->wake_up_semaphore = CreateSemaphore (NULL, 0, 100, NULL)) == NULL)
+       g_error ("Cannot create wake-up semaphore: %s", g_win32_error_message (GetLastError ()));
+      context->wake_up_rec.fd = (gint) context->wake_up_semaphore;
+      context->wake_up_rec.events = G_IO_IN;
 #ifdef G_MAIN_POLL_DEBUG
-         g_print ("wake-up semaphore: %#x\n", (guint) context->wake_up_semaphore);
+      g_print ("wake-up semaphore: %#x\n", (guint) context->wake_up_semaphore);
 #endif
-         g_main_context_add_poll_unlocked (context, 0, &context->wake_up_rec);
+      g_main_context_add_poll_unlocked (context, 0, &context->wake_up_rec);
 #endif
-       }
+    }
 #endif
 
+  return context;
+}
+
+/**
+ * g_main_context_get:
+ * @thread: a #GThread
+ * 
+ * Retrieves the main loop context for a particular thread. This
+ * will create the main context for the thread if none previously
+ * existed. The context will exist until the thread terminates.
+ * 
+ * Return value: the main loop context for @thread.
+ **/
+GMainContext *
+g_main_context_get (GThread *thread)
+{
+  static GStaticPrivate private_key = G_STATIC_PRIVATE_INIT;
+  GMainContext *context;
+
+  g_return_val_if_fail (thread != NULL, NULL);
+
+  if (g_thread_supported ())
+    context = g_static_private_get_for_thread (&private_key, thread);
+  else
+    context = default_main_context;
+
+  if (!context)
+    {
+      context = g_main_context_new (thread);
+
       if (g_thread_supported ())
        g_static_private_set_for_thread (&private_key, thread,
                                         context,
diff --git a/gmain.h b/gmain.h
index dd500c6e83c6b7863dadf8eab8a1d4d1f50e72a3..23dd58c5ccc2610e32194fda8be58a80268e44df 100644 (file)
--- a/gmain.h
+++ b/gmain.h
@@ -143,6 +143,9 @@ GSource      *g_main_context_find_source_by_funcs_user_data (GMainContext *conte
 
 /* Low level functions for implementing custom main loops.
  */
+GMainContext *g_main_context_new     (GThread *thread);
+void          g_main_context_destroy (GMainContext *context);
+
 gboolean g_main_context_prepare  (GMainContext *context,
                                  gint         *priority);
 gint     g_main_context_query    (GMainContext *context,
index 45ec9740c63b1e6a53db76cbe99b8afa3ccaec0f..ab686b4fc72318b2b058ac4e3b8193bc1aaa9ab4 100644 (file)
@@ -1,3 +1,11 @@
+2000-12-12  Elliot Lee  <sopwith@redhat.com>
+
+       * Makefile.am:
+         . You have to 'touch oldest-source-stamp' if you want to avoid having
+         the Makefile constantly rebuild itself.
+         . Fix marshaller generation rules to work with srcdir != builddir
+           (there were issues with trying to run "./glib-genmarshal", etc.)
+
 Mon Dec 11 04:44:11 2000  Tim Janik  <timj@gtk.org>
 
        * gboxed.c: fixed dealing with collection/lcopy of NULL values.
index 0c37fdff033e9e115423100d0df4b52001c50191..c722ddbcd98d77e7e63e7970fa559585ca655bc6 100644 (file)
@@ -102,7 +102,11 @@ EXTRA_DIST += $(gruntime_built_sources)
 gen_sources = xgen-gmh xgen-gmc xgen-gms
 CLEANFILES += $(gen_sources)
 Makefile: oldest-source-stamp  # oh boy, does automake SUCK!
+
 oldest-source-stamp: $(gruntime_built_sources)
+       @touch oldest-source-stamp
+CLEANFILES+=oldest-source-stamp
+
 $(OBJECTS): oldest-source-stamp  ${gruntime_built_public_sources} # this is our oldest file, used for implicit auto-generation deps
 # initial creation of the real stamp-* files
 gmarshal.h:    # never add deps here
@@ -114,24 +118,23 @@ gmarshal.h:       # never add deps here
 # srcdir to be writable, passing --disable-rebuilds to
 # ../configure will supress all autogeneration rules.
 $(srcdir)/stamp-gmarshal.h: @REBUILD@ gmarshal.list gmarshal.h glib-genmarshal
-       cd $(srcdir) \
-       && echo "#ifndef __G_MARSHAL_H__" > xgen-gmh \
+       echo "#ifndef __G_MARSHAL_H__" > xgen-gmh \
        && echo "#define __G_MARSHAL_H__" >> xgen-gmh \
-       && ./glib-genmarshal --nostdinc --prefix=g_cclosure_marshal gmarshal.list --header >> xgen-gmh \
+       && ./glib-genmarshal --nostdinc --prefix=g_cclosure_marshal $(srcdir)/gmarshal.list --header >> xgen-gmh \
        && echo "#endif /* __G_MARSHAL_H__ */" >> xgen-gmh \
-       && (cmp -s xgen-gmh gmarshal.h || cp xgen-gmh gmarshal.h) \
+       && (cmp -s xgen-gmh $(srcdir)/gmarshal.h || cp xgen-gmh $(srcdir)/gmarshal.h) \
        && rm -f xgen-gmh xgen-gmh~ \
-       && echo timestamp > $(@F)
+       && echo timestamp > $@
+
 $(srcdir)/gmarshal.c: @REBUILD@ $(srcdir)/stamp-gmarshal.h
-       cd $(srcdir) \
-       && ./glib-genmarshal --nostdinc --prefix=g_cclosure_marshal gmarshal.list --body >> xgen-gmc \
-       && cp xgen-gmc gmarshal.c \
+       ./glib-genmarshal --nostdinc --prefix=g_cclosure_marshal $(srcdir)/gmarshal.list --body >> xgen-gmc \
+       && cp xgen-gmc $(srcdir)/gmarshal.c \
        && rm -f xgen-gmc xgen-gmc~
+
 $(srcdir)/gmarshal.strings: @REBUILD@ $(srcdir)/gmarshal.list
-       cd $(srcdir) \
-       && grep '^[A-Z]' $(srcdir)/gmarshal.list \
+       grep '^[A-Z]' $(srcdir)/gmarshal.list \
        | sed -e 's/^/"g_cclosure_marshal_/' -e 's/:/__/' -e 's/,/_/g' -e 's/$$/",/' > xgen-gms \
-       && cp xgen-gms gmarshal.strings \
+       && cp xgen-gms $(srcdir)/gmarshal.strings \
        && rm -f xgen-gms xgen-gms~
 glib-genmarshal.o: gmarshal.strings