(root)/
glib-2.79.0/
gobject/
tests/
dynamictests.c
       1  /* GLib testing framework examples and tests
       2   * Copyright (C) 2008 Imendio AB
       3   * Authors: Tim Janik
       4   *
       5   * SPDX-License-Identifier: LicenseRef-old-glib-tests
       6   *
       7   * This work is provided "as is"; redistribution and modification
       8   * in whole or in part, in any medium, physical or electronic is
       9   * permitted without restriction.
      10   *
      11   * This work is distributed in the hope that it will be useful,
      12   * but WITHOUT ANY WARRANTY; without even the implied warranty of
      13   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
      14   *
      15   * In no event shall the authors or contributors be liable for any
      16   * direct, indirect, incidental, special, exemplary, or consequential
      17   * damages (including, but not limited to, procurement of substitute
      18   * goods or services; loss of use, data, or profits; or business
      19   * interruption) however caused and on any theory of liability, whether
      20   * in contract, strict liability, or tort (including negligence or
      21   * otherwise) arising in any way out of the use of this software, even
      22   * if advised of the possibility of such damage.
      23   */
      24  #include <glib.h>
      25  #include <glib-object.h>
      26  
      27  /* This test tests the macros for defining dynamic types.
      28   */
      29  
      30  static GMutex sync_mutex;
      31  static gboolean loaded = FALSE;
      32  
      33  /* MODULE */
      34  typedef struct _TestModule      TestModule;
      35  typedef struct _TestModuleClass TestModuleClass;
      36  
      37  #define TEST_TYPE_MODULE              (test_module_get_type ())
      38  #define TEST_MODULE(module)           (G_TYPE_CHECK_INSTANCE_CAST ((module), TEST_TYPE_MODULE, TestModule))
      39  #define TEST_MODULE_CLASS(class)      (G_TYPE_CHECK_CLASS_CAST ((class), TEST_TYPE_MODULE, TestModuleClass))
      40  #define TEST_IS_MODULE(module)        (G_TYPE_CHECK_INSTANCE_TYPE ((module), TEST_TYPE_MODULE))
      41  #define TEST_IS_MODULE_CLASS(class)   (G_TYPE_CHECK_CLASS_TYPE ((class), TEST_TYPE_MODULE))
      42  #define TEST_MODULE_GET_CLASS(module) (G_TYPE_INSTANCE_GET_CLASS ((module), TEST_TYPE_MODULE, TestModuleClass))
      43  typedef void (*TestModuleRegisterFunc) (GTypeModule *module);
      44  
      45  struct _TestModule
      46  {
      47    GTypeModule parent_instance;
      48  
      49    TestModuleRegisterFunc register_func;
      50  };
      51  
      52  struct _TestModuleClass
      53  {
      54    GTypeModuleClass parent_class;
      55  };
      56  
      57  static GType test_module_get_type (void);
      58  
      59  static gboolean
      60  test_module_load (GTypeModule *module)
      61  {
      62    TestModule *test_module = TEST_MODULE (module);
      63  
      64    test_module->register_func (module);
      65  
      66    return TRUE;
      67  }
      68  
      69  static void
      70  test_module_unload (GTypeModule *module)
      71  {
      72  }
      73  
      74  static void
      75  test_module_class_init (TestModuleClass *class)
      76  {
      77    GTypeModuleClass *module_class = G_TYPE_MODULE_CLASS (class);
      78  
      79    module_class->load = test_module_load;
      80    module_class->unload = test_module_unload;
      81  }
      82  
      83  static GType test_module_get_type (void)
      84  {
      85    static GType object_type = 0;
      86  
      87    if (!object_type) {
      88      static const GTypeInfo object_info =
      89        {
      90  	sizeof (TestModuleClass),
      91  	(GBaseInitFunc) NULL,
      92  	(GBaseFinalizeFunc) NULL,
      93  	(GClassInitFunc) test_module_class_init,
      94  	(GClassFinalizeFunc) NULL,
      95  	NULL,
      96  	sizeof (TestModule),
      97  	0,
      98          (GInstanceInitFunc)NULL,
      99          NULL,
     100        };
     101      object_type = g_type_register_static (G_TYPE_TYPE_MODULE, "TestModule", &object_info, 0);
     102    }
     103    return object_type;
     104  }
     105  
     106  
     107  static GTypeModule *
     108  test_module_new (TestModuleRegisterFunc register_func)
     109  {
     110    TestModule *test_module = g_object_new (TEST_TYPE_MODULE, NULL);
     111    GTypeModule *module = G_TYPE_MODULE (test_module);
     112  
     113    test_module->register_func = register_func;
     114  
     115    /* Register the types initially */
     116    g_type_module_use (module);
     117    g_type_module_unuse (module);
     118  
     119    return G_TYPE_MODULE (module);
     120  }
     121  
     122  
     123  
     124  #define DYNAMIC_OBJECT_TYPE (dynamic_object_get_type ())
     125  
     126  typedef GObject DynamicObject;
     127  typedef struct _DynamicObjectClass DynamicObjectClass;
     128  
     129  struct _DynamicObjectClass
     130  {
     131    GObjectClass parent_class;
     132    guint val;
     133  };
     134  
     135  static GType dynamic_object_get_type (void);
     136  G_DEFINE_DYNAMIC_TYPE(DynamicObject, dynamic_object, G_TYPE_OBJECT)
     137  
     138  static void
     139  dynamic_object_class_init (DynamicObjectClass *class)
     140  {
     141    class->val = 42;
     142    g_assert (loaded == FALSE);
     143    loaded = TRUE;
     144  }
     145  
     146  static void
     147  dynamic_object_class_finalize (DynamicObjectClass *class)
     148  {
     149    g_assert (loaded == TRUE);
     150    loaded = FALSE;
     151  }
     152  
     153  static void
     154  dynamic_object_init (DynamicObject *dynamic_object)
     155  {
     156  }
     157  
     158  
     159  static void
     160  module_register (GTypeModule *module)
     161  {
     162    dynamic_object_register_type (module);
     163  }
     164  
     165  #define N_THREADS 100
     166  #define N_REFS 10000
     167  
     168  static gpointer
     169  ref_unref_thread (gpointer data)
     170  {
     171    gint i;
     172    /* first, synchronize with other threads,
     173     */
     174    if (g_test_verbose())
     175      g_printerr ("WAITING!\n");
     176    g_mutex_lock (&sync_mutex);
     177    g_mutex_unlock (&sync_mutex);
     178    if (g_test_verbose ())
     179      g_printerr ("STARTING\n");
     180  
     181    /* ref/unref the klass 10000000 times */
     182    for (i = N_REFS; i; i--) {
     183      if (g_test_verbose ())
     184        if (i % 10)
     185  	g_printerr ("%d\n", i);
     186      g_type_class_unref (g_type_class_ref ((GType) data));
     187    }
     188  
     189    if (g_test_verbose())
     190      g_printerr ("DONE !\n");
     191  
     192    return NULL;
     193  }
     194  
     195  static void
     196  test_multithreaded_dynamic_type_init (void)
     197  {
     198    GTypeModule *module;
     199    DynamicObjectClass *class;
     200    /* Create N_THREADS threads that are going to just ref/unref a class */
     201    GThread *threads[N_THREADS];
     202    guint i;
     203  
     204    module = test_module_new (module_register);
     205    g_assert (module != NULL);
     206  
     207    /* Not loaded until we call ref for the first time */
     208    class = g_type_class_peek (DYNAMIC_OBJECT_TYPE);
     209    g_assert (class == NULL);
     210    g_assert (!loaded);
     211  
     212    /* pause newly created threads */
     213    g_mutex_lock (&sync_mutex);
     214  
     215    /* create threads */
     216    for (i = 0; i < N_THREADS; i++) {
     217      threads[i] = g_thread_new ("test", ref_unref_thread, (gpointer) DYNAMIC_OBJECT_TYPE);
     218    }
     219  
     220    /* execute threads */
     221    g_mutex_unlock (&sync_mutex);
     222  
     223    for (i = 0; i < N_THREADS; i++) {
     224      g_thread_join (threads[i]);
     225    }
     226  }
     227  
     228  enum
     229  {
     230    PROP_0,
     231    PROP_FOO
     232  };
     233  
     234  typedef struct _DynObj DynObj;
     235  typedef struct _DynObjClass DynObjClass;
     236  typedef struct _DynIfaceInterface DynIfaceInterface;
     237  
     238  struct _DynObj
     239  {
     240    GObject obj;
     241  
     242    gint foo;
     243  };
     244  
     245  struct _DynObjClass
     246  {
     247    GObjectClass class;
     248  };
     249  
     250  struct _DynIfaceInterface
     251  {
     252    GTypeInterface iface;
     253  };
     254  
     255  static void dyn_obj_iface_init (DynIfaceInterface *iface);
     256  
     257  static GType dyn_iface_get_type (void);
     258  G_DEFINE_INTERFACE (DynIface, dyn_iface, G_TYPE_OBJECT)
     259  
     260  static GType dyn_obj_get_type (void);
     261  G_DEFINE_DYNAMIC_TYPE_EXTENDED(DynObj, dyn_obj, G_TYPE_OBJECT, 0,
     262                        G_IMPLEMENT_INTERFACE_DYNAMIC(dyn_iface_get_type (), dyn_obj_iface_init))
     263  
     264  
     265  static void
     266  dyn_iface_default_init (DynIfaceInterface *iface)
     267  {
     268    g_object_interface_install_property (iface,
     269      g_param_spec_int ("foo", NULL, NULL, 0, 100, 0, G_PARAM_READWRITE));
     270  }
     271  
     272  static void
     273  dyn_obj_iface_init (DynIfaceInterface *iface)
     274  {
     275  }
     276  
     277  static void
     278  dyn_obj_init (DynObj *obj)
     279  {
     280    obj->foo = 0;
     281  }
     282  
     283  static void
     284  set_prop (GObject      *object,
     285            guint         prop_id,
     286            const GValue *value,
     287            GParamSpec   *pspec)
     288  {
     289    DynObj *obj = (DynObj *)object;
     290  
     291    switch (prop_id)
     292      {
     293      case PROP_FOO:
     294        obj->foo = g_value_get_int (value);
     295        break;
     296      default:
     297        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
     298        break;
     299      }
     300  }
     301  
     302  static void
     303  get_prop (GObject    *object,
     304            guint       prop_id,
     305            GValue     *value,
     306            GParamSpec *pspec)
     307  {
     308    DynObj *obj = (DynObj *)object;
     309  
     310    switch (prop_id)
     311      {
     312      case PROP_FOO:
     313        g_value_set_int (value, obj->foo);
     314        break;
     315      default:
     316        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
     317        break;
     318      }
     319  }
     320  
     321  static void
     322  dyn_obj_class_init (DynObjClass *class)
     323  {
     324    GObjectClass *object_class = G_OBJECT_CLASS (class);
     325  
     326    object_class->set_property = set_prop;
     327    object_class->get_property = get_prop;
     328  
     329    g_object_class_override_property (object_class, PROP_FOO, "foo");
     330  }
     331  
     332  static void
     333  dyn_obj_class_finalize (DynObjClass *class)
     334  {
     335  }
     336  
     337  static void
     338  mod_register (GTypeModule *module)
     339  {
     340    dyn_obj_register_type (module);
     341  }
     342  
     343  static void
     344  test_dynamic_interface_properties (void)
     345  {
     346    GTypeModule *module;
     347    DynObj *obj;
     348    gint val;
     349  
     350    module = test_module_new (mod_register);
     351    g_assert (module != NULL);
     352  
     353    obj = g_object_new (dyn_obj_get_type (), "foo", 1, NULL);
     354    g_object_get (obj, "foo", &val, NULL);
     355    g_assert_cmpint (val, ==, 1);
     356  
     357    g_object_unref (obj);
     358  }
     359  
     360  int
     361  main (int   argc,
     362        char *argv[])
     363  {
     364    g_test_init (&argc, &argv, NULL);
     365  
     366    g_test_add_func ("/GObject/threaded-dynamic-ref-unref-init", test_multithreaded_dynamic_type_init);
     367    g_test_add_func ("/GObject/dynamic-interface-properties", test_dynamic_interface_properties);
     368  
     369    return g_test_run();
     370  }