(root)/
glib-2.79.0/
gobject/
tests/
objects-refcount1.c
       1  #include <glib.h>
       2  #include <glib-object.h>
       3  
       4  #ifdef G_OS_UNIX
       5  #include <unistd.h>
       6  #endif
       7  
       8  #define G_TYPE_TEST                (my_test_get_type ())
       9  #define MY_TEST(test)              (G_TYPE_CHECK_INSTANCE_CAST ((test), G_TYPE_TEST, GTest))
      10  #define MY_IS_TEST(test)           (G_TYPE_CHECK_INSTANCE_TYPE ((test), G_TYPE_TEST))
      11  #define MY_TEST_CLASS(tclass)      (G_TYPE_CHECK_CLASS_CAST ((tclass), G_TYPE_TEST, GTestClass))
      12  #define MY_IS_TEST_CLASS(tclass)   (G_TYPE_CHECK_CLASS_TYPE ((tclass), G_TYPE_TEST))
      13  #define MY_TEST_GET_CLASS(test)    (G_TYPE_INSTANCE_GET_CLASS ((test), G_TYPE_TEST, GTestClass))
      14  
      15  typedef struct _GTest GTest;
      16  typedef struct _GTestClass GTestClass;
      17  
      18  #if G_GNUC_CHECK_VERSION (4, 0)
      19  /* Increase the alignment of GTest to check whether
      20   * G_TYPE_CHECK_INSTANCE_CAST() would trigger a "-Wcast-align=strict" warning.
      21   * That would happen, when trying to cast a "GObject*" to "GTest*", if latter
      22   * has larger alignment.
      23   *
      24   * Note that merely adding a int64 field to GTest does not increase the
      25   * alignment above 4 bytes on i386, hence use the __attribute__((__aligned__())).
      26   */
      27  #define _GTest_increase_alignment __attribute__((__aligned__(__alignof(gint64))))
      28  #else
      29  #define _GTest_increase_alignment
      30  #endif
      31  
      32  struct _GTest
      33  {
      34    GObject object;
      35  
      36    /* See _GTest_increase_alignment. */
      37    long double increase_alignment2;
      38  } _GTest_increase_alignment;
      39  
      40  struct _GTestClass
      41  {
      42    GObjectClass parent_class;
      43  };
      44  
      45  static GType my_test_get_type (void);
      46  static gint stopping;  /* (atomic) */
      47  
      48  static void my_test_class_init (GTestClass * klass);
      49  static void my_test_init (GTest * test);
      50  static void my_test_dispose (GObject * object);
      51  
      52  static GObjectClass *parent_class = NULL;
      53  
      54  static GType
      55  my_test_get_type (void)
      56  {
      57    static GType test_type = 0;
      58  
      59    if (!test_type) {
      60      const GTypeInfo test_info = {
      61        sizeof (GTestClass),
      62        NULL,
      63        NULL,
      64        (GClassInitFunc) my_test_class_init,
      65        NULL,
      66        NULL,
      67        sizeof (GTest),
      68        0,
      69        (GInstanceInitFunc) my_test_init,
      70        NULL
      71      };
      72  
      73      test_type = g_type_register_static (G_TYPE_OBJECT, "GTest",
      74          &test_info, 0);
      75    }
      76    return test_type;
      77  }
      78  
      79  static void
      80  my_test_class_init (GTestClass * klass)
      81  {
      82    GObjectClass *gobject_class;
      83  
      84    gobject_class = (GObjectClass *) klass;
      85    parent_class = g_type_class_ref (G_TYPE_OBJECT);
      86  
      87    gobject_class->dispose = my_test_dispose;
      88  }
      89  
      90  static void
      91  my_test_init (GTest * test)
      92  {
      93    g_test_message ("init %p\n", test);
      94  }
      95  
      96  static void
      97  my_test_dispose (GObject * object)
      98  {
      99    GTest *test;
     100  
     101    test = MY_TEST (object);
     102  
     103    g_test_message ("dispose %p!\n", test);
     104  
     105    G_OBJECT_CLASS (parent_class)->dispose (object);
     106  }
     107  
     108  static void
     109  my_test_do_refcount (GTest * test)
     110  {
     111    g_object_ref (test);
     112    g_object_unref (test);
     113  }
     114  
     115  static gpointer
     116  run_thread (GTest * test)
     117  {
     118    gint i = 1;
     119  
     120    while (!g_atomic_int_get (&stopping)) {
     121      my_test_do_refcount (test);
     122      if ((i++ % 10000) == 0) {
     123          g_thread_yield (); /* force context switch */
     124      }
     125    }
     126  
     127    return NULL;
     128  }
     129  
     130  static void
     131  test_refcount_object_basics (void)
     132  {
     133    guint i;
     134    GTest *test1, *test2;
     135    GArray *test_threads;
     136    const guint n_threads = 5;
     137  
     138    test1 = g_object_new (G_TYPE_TEST, NULL);
     139    test2 = g_object_new (G_TYPE_TEST, NULL);
     140  
     141    test_threads = g_array_new (FALSE, FALSE, sizeof (GThread *));
     142  
     143    g_atomic_int_set (&stopping, 0);
     144  
     145    for (i = 0; i < n_threads; i++) {
     146      GThread *thread;
     147  
     148      thread = g_thread_new (NULL, (GThreadFunc) run_thread, test1);
     149      g_array_append_val (test_threads, thread);
     150  
     151      thread = g_thread_new (NULL, (GThreadFunc) run_thread, test2);
     152      g_array_append_val (test_threads, thread);
     153    }
     154  
     155    g_usleep (5000000);
     156    g_atomic_int_set (&stopping, 1);
     157  
     158    /* join all threads */
     159    for (i = 0; i < 2 * n_threads; i++) {
     160      GThread *thread;
     161  
     162      thread = g_array_index (test_threads, GThread *, i);
     163      g_thread_join (thread);
     164    }
     165  
     166    g_object_unref (test1);
     167    g_object_unref (test2);
     168    g_array_unref (test_threads);
     169  }
     170  
     171  int
     172  main (int argc, gchar *argv[])
     173  {
     174    g_log_set_always_fatal (G_LOG_LEVEL_WARNING |
     175                            G_LOG_LEVEL_CRITICAL |
     176                            g_log_set_always_fatal (G_LOG_FATAL_MASK));
     177  
     178    g_test_init (&argc, &argv, NULL);
     179  
     180    g_test_add_func ("/gobject/refcount/object-basics", test_refcount_object_basics);
     181  
     182    return g_test_run ();
     183  }