From 445e29b06a59db30b22898bac39e6315a380bbc9 Mon Sep 17 00:00:00 2001
From: rds <rds>
Date: Mon, 12 Jan 2009 11:15:21 +0000
Subject: [PATCH] More permanent fix for base object thread issues...

---
 src/zmapUtils/zmapBase.c   | 213 +++++++++++++++++++++++++------------
 src/zmapUtils/zmapBase_I.h |  11 +-
 2 files changed, 156 insertions(+), 68 deletions(-)

diff --git a/src/zmapUtils/zmapBase.c b/src/zmapUtils/zmapBase.c
index 44baffd1a..dc44b3586 100755
--- a/src/zmapUtils/zmapBase.c
+++ b/src/zmapUtils/zmapBase.c
@@ -27,9 +27,9 @@
  *
  * Exported functions: See ZMap/zmapBase.h
  * HISTORY:
- * Last edited: Jan 12 09:14 2009 (rds)
+ * Last edited: Jan 12 11:11 2009 (rds)
  * Created: Thu Jun 12 12:02:12 2008 (rds)
- * CVS info:   $Id: zmapBase.c,v 1.6 2009-01-12 09:16:11 rds Exp $
+ * CVS info:   $Id: zmapBase.c,v 1.7 2009-01-12 11:15:21 rds Exp $
  *-------------------------------------------------------------------
  */
 
@@ -57,7 +57,8 @@ static void zmap_base_dispose      (GObject *object);
 static void zmap_base_finalize     (GObject *object);
 #endif /* ZMAP_BASE_NEEDS_DISPOSE_FINALIZE */
 
-static gboolean zmapBaseCopy(ZMapBase src, ZMapBase *dest_out, gboolean reference_copy);
+static gboolean zmapBaseCopy(ZMapBase src, ZMapBase *dest_out, gboolean copy_by_reference);
+static gboolean zmapBaseCopyValue(const GValue *src_value, GValue *dest_value, ZMapBaseValueCopyFunc value_copy);
 static void zmapBaseCopyConstructor(const GValue *src_value, GValue *dest_value);
 
 
@@ -70,9 +71,7 @@ GType zMapBaseGetType (void)
   
   if (type == 0) 
     {
-      GTypeValueTable *vtable;
-      GTypeValueTable *gobject_table;
-      static GTypeInfo info = {
+      static const GTypeInfo info = {
 	sizeof (zmapBaseClass),
 	(GBaseInitFunc)      zmap_base_base_init,
 	(GBaseFinalizeFunc)  NULL,
@@ -84,38 +83,50 @@ GType zMapBaseGetType (void)
 	(GInstanceInitFunc) zmap_base_inst_init,
 	NULL
       };
-#ifdef RDS_DONT_INCLUDE
-      gobject_table = g_type_value_table_peek(G_TYPE_OBJECT);
 
-      vtable = g_new0(GTypeValueTable, 1);
-
-      memcpy(vtable, gobject_table, sizeof(GTypeValueTable));
-
-      info.value_table = vtable;
-#endif
       type = g_type_register_static (G_TYPE_OBJECT, "ZMapBase", &info, (GTypeFlags)0);
   }
   
   return type;
 }
 
-/* Copy by reference */
+/*!
+ * \brief Copy a ZMapBase or ZMapBase Derived object.  The copy is
+ * done by reference only and ultimately only calls g_object_ref()
+ *
+ * @param      The original object
+ *
+ * @return     The original object with a ref count + 1.
+ */
 ZMapBase zMapBaseCopy(ZMapBase src)
 {
   ZMapBase dest = NULL;
-  gboolean done = TRUE;
+  gboolean copy_by_reference = TRUE;
 
-  done = zmapBaseCopy(src, &dest, done);
+  /* Copy by reference only. g_object_ref() is all that happens */
+  zmapBaseCopy(src, &dest, copy_by_reference);
 
   return dest;
 }
 
-/* Copy constructor. */
+
+/*!
+ * \brief Copy a ZMapBase or ZMapBase Derived object. The copy is a
+ * deep copy and results in the getting and setting of each property
+ * in the original and new objects (respectively).
+ *
+ * @param    The original object
+ * @param    The location to store the new object.
+ *
+ * @return   True if success was met.
+ */
 gboolean zMapBaseCCopy(ZMapBase src, ZMapBase *dest_out)
 {
+  gboolean copy_by_reference = FALSE;
   gboolean done = FALSE;
 
-  done = zmapBaseCopy(src, dest_out, done);
+  /* Deep Copy... */
+  done = zmapBaseCopy(src, dest_out, copy_by_reference);
 
   return done;
 }
@@ -132,6 +143,8 @@ static void zmap_base_base_init   (ZMapBaseClass zmap_base_class)
 {
   zmap_base_class->copy_set_property = NULL;
 
+  zmap_base_class->value_copy = zmapBaseCopyConstructor;
+
   return ;
 }
 
@@ -232,67 +245,136 @@ static void zmap_base_finalize     (GObject *object)
 
 
 /* INTERNAL */
-G_LOCK_DEFINE_STATIC(thread_lock_G);
 
-static gboolean zmapBaseCopy(ZMapBase src, ZMapBase *dest_out, gboolean reference_copy)
+
+/*
+ * zmapBaseCopy and zmapBaseCopyValue are the covering functions to
+ * handle the copying of ZMapBase and their derived objects.  They
+ * really just cover the zmapBaseCopyConstructor() or the default
+ * g_value_object_copy_value(). zmapBaseCopyValue is a direct copy
+ * of g_value_copy() with a small alteration so that we pass in the
+ * GTypeValueTable->value_copy function rather than have it be used
+ * directly from the table of the GType (g_type_value_table_peek).
+ */
+
+/*!
+ * \brief Copy a ZMapBase or derived object, either by reference or
+ * using class defined/overridden copy function.
+ *
+ * @param    The original object
+ * @param    The location to store the new object
+ * @param    Flag for copy by reference. TRUE  = Copy by reference
+ *           FALSE = Use ZMapBaseClass->value_copy
+ *
+ * @return   How successful copy was. TRUE == Success
+ */
+static gboolean zmapBaseCopy(ZMapBase src, ZMapBase *dest_out, gboolean copy_by_reference)
 {
+  ZMapBaseValueCopyFunc value_copy_func = NULL;
+  GValue src_value = {0}, dest_value = {0};
   ZMapBase dest = NULL;
-  ZMapBaseClass zmap_class;
-  GObject *gobject_src;
+  gboolean done = FALSE;
   GType gobject_type;
-  gboolean copied = FALSE;
-  GTypeValueTable *value_table;
-  gpointer value_copy;
 
-  g_return_val_if_fail(dest_out != NULL, FALSE);
-  gobject_src   = G_OBJECT(src);
-  gobject_type  = G_TYPE_FROM_INSTANCE(src);
-  zmap_class    = ZMAP_BASE_GET_CLASS(gobject_src);
-
-  G_LOCK(thread_lock_G);
-  /* get vtable */
-  value_table = g_type_value_table_peek(gobject_type);
-  /* save current value copy */
-  value_copy = value_table->value_copy;
-  
-  if(reference_copy || zmap_class->copy_set_property)
+  if(dest_out)
     {
-      GValue src_value = {0}, dest_value = {0};
+      gobject_type  = G_TYPE_FROM_INSTANCE(src);
       
-      g_value_init(&src_value,  gobject_type);
-      g_value_init(&dest_value, gobject_type);
-      
-      g_value_set_object(&src_value,  src);
+      if(copy_by_reference)
+	{
+	  GTypeValueTable *value_table;
 
-      if(!reference_copy)
-	value_table->value_copy = zmapBaseCopyConstructor;
+	  /* get vtable */
+	  value_table = g_type_value_table_peek(gobject_type);
 
-      /* g_value_copy memset 0's dest_value.data so don't set here,
-       * but in value_table->value_copy */
-      g_value_copy(&src_value, &dest_value);
-      
-      /* return it to caller */
-      dest      = g_value_get_object(&dest_value);
-      *dest_out = dest;
+	  value_copy_func = value_table->value_copy;
+	}
+      else
+	{
+	  ZMapBaseClass base_class = NULL;
+
+	  base_class = ZMAP_BASE_GET_CLASS(src);
 
-      g_value_unset(&src_value);
-      g_value_unset(&dest_value);
+	  /* Use the class defined value_copy */
+	  value_copy_func = base_class->value_copy;
+	}
 
-      copied = TRUE;
+      if(value_copy_func != NULL)
+	{
+	  g_value_init(&src_value,  gobject_type);
+	  g_value_init(&dest_value, gobject_type);
+	  
+	  g_value_set_object(&src_value,  src);
+	  
+	  if((done = zmapBaseCopyValue(&src_value, &dest_value, value_copy_func)))
+	    {
+	      /* return it to caller */
+	      dest      = g_value_get_object(&dest_value);
+	      *dest_out = dest;
+	    }
+	  
+	  g_value_unset(&src_value);
+	  g_value_unset(&dest_value);
+	}
     }
-  
-  /* restore */
-  if(value_copy != zmapBaseCopyConstructor)
-    value_table->value_copy = value_copy;
-  else
-    g_warning("Thread locking failed...");
-    
-  G_UNLOCK(thread_lock_G);
-
-  return copied;
+
+  return done;
 }
 
+/*!
+ * \brief Almost identical to g_value_copy().  We pass in the
+ * value_copy function though.
+ *
+ * @param    The original GValue
+ * @param    The new GValue
+ * @param    The function to use to copy the GValue from 
+ *           origin to new.
+ *
+ * @return   How successful copying was. TRUE == Success
+ */
+static gboolean zmapBaseCopyValue(const GValue *src_value, GValue *dest_value, ZMapBaseValueCopyFunc value_copy)
+{
+  gboolean done = FALSE;
 
+  g_return_val_if_fail (G_IS_VALUE (src_value), FALSE);
+  g_return_val_if_fail (G_IS_VALUE (dest_value), FALSE);
+  g_return_val_if_fail (g_value_type_compatible (G_VALUE_TYPE (src_value), G_VALUE_TYPE (dest_value)), FALSE);
+  
+  if (value_copy && src_value != dest_value)
+    {
+      GType dest_type = G_VALUE_TYPE (dest_value);
+      GTypeValueTable *value_table = g_type_value_table_peek (dest_type);
+
+      /* make sure dest_value's value is free()d */
+      if (value_table->value_free)
+	value_table->value_free (dest_value);
+      
+      /* setup and copy */
+      g_value_init(dest_value, dest_type);
+
+      value_copy(src_value, dest_value);
+
+      done = TRUE;
+    }
+
+  return done;
+}
+
+/*!
+ * \brief Copy all data from one ZMapBase, or derived, object to
+ * another.  This involves _creating_ a new ZMapBase (g_object_new()),
+ * getting properties from the original one and setting them on the
+ * new one.  This avoids duplicating this code throughout any objects 
+ * we need to do this with.
+ *
+ * This function is called by zmapBaseCopyValue in the line 
+ * value_copy(src_value, dest_value);
+ *
+ * @param   The original GValue
+ * @param   The new GValue (EMPTY)
+ *
+ * @return  Nothing
+ */
 static void zmapBaseCopyConstructor(const GValue *src_value, GValue *dest_value)
 {
   GObject      *gobject_src;
@@ -368,7 +450,6 @@ static void zmapBaseCopyConstructor(const GValue *src_value, GValue *dest_value)
       g_value_set_object(dest_value, gobject_dest);
     }
 
-
   return ;
 }
 
diff --git a/src/zmapUtils/zmapBase_I.h b/src/zmapUtils/zmapBase_I.h
index 415e0ac6f..d3c44c6b1 100755
--- a/src/zmapUtils/zmapBase_I.h
+++ b/src/zmapUtils/zmapBase_I.h
@@ -27,9 +27,9 @@
  *
  * Exported functions: See XXXXXXXXXXXXX.h
  * HISTORY:
- * Last edited: Jun 13 17:09 2008 (rds)
+ * Last edited: Jan 12 10:03 2009 (rds)
  * Created: Thu Jun 12 12:02:56 2008 (rds)
- * CVS info:   $Id: zmapBase_I.h,v 1.2 2008-06-25 14:01:52 rds Exp $
+ * CVS info:   $Id: zmapBase_I.h,v 1.3 2009-01-12 11:15:36 rds Exp $
  *-------------------------------------------------------------------
  */
 
@@ -43,6 +43,8 @@
 #define ZMAP_PARAM_STATIC_RO (ZMAP_PARAM_STATIC | G_PARAM_READABLE)
 #define ZMAP_PARAM_STATIC_WO (ZMAP_PARAM_STATIC | G_PARAM_WRITABLE)
 
+typedef void (* ZMapBaseValueCopyFunc)(const GValue *src_value, GValue *dest_value);
+
 typedef struct _zmapBaseStruct
 {
   GObject __parent__;
@@ -58,6 +60,11 @@ typedef struct _zmapBaseClassStruct
   /* similar to gobject_class->set_property, but required for copy construction */
   GObjectSetPropertyFunc copy_set_property;
 
+  /* Our version of the GTypeValueTable->value_copy function. 
+   * Ordinarily we'd just use the value_table member of GTypeInfo,
+   * but threading scuppers that. */
+  void (*value_copy)(const GValue *src_value, GValue *dest_value);
+
 } zmapBaseClassStruct;
 
 #endif /* __ZMAP_BASE_I_H__ */
-- 
GitLab