Home | History | Annotate | Download | only in refcount
      1 #include <unistd.h>
      2 #include <glib.h>
      3 #include <glib-object.h>
      4 
      5 #define G_TYPE_TEST               (my_test_get_type ())
      6 #define MY_TEST(test)              (G_TYPE_CHECK_INSTANCE_CAST ((test), G_TYPE_TEST, GTest))
      7 #define MY_IS_TEST(test)           (G_TYPE_CHECK_INSTANCE_TYPE ((test), G_TYPE_TEST))
      8 #define MY_TEST_CLASS(tclass)      (G_TYPE_CHECK_CLASS_CAST ((tclass), G_TYPE_TEST, GTestClass))
      9 #define MY_IS_TEST_CLASS(tclass)   (G_TYPE_CHECK_CLASS_TYPE ((tclass), G_TYPE_TEST))
     10 #define MY_TEST_GET_CLASS(test)    (G_TYPE_INSTANCE_GET_CLASS ((test), G_TYPE_TEST, GTestClass))
     11 
     12 typedef struct _GTest GTest;
     13 typedef struct _GTestClass GTestClass;
     14 
     15 struct _GTest
     16 {
     17   GObject object;
     18 };
     19 
     20 struct _GTestClass
     21 {
     22   GObjectClass parent_class;
     23 };
     24 
     25 static GType my_test_get_type (void);
     26 static volatile gboolean stopping;
     27 
     28 static void my_test_class_init (GTestClass * klass);
     29 static void my_test_init (GTest * test);
     30 static void my_test_dispose (GObject * object);
     31 
     32 static GObjectClass *parent_class = NULL;
     33 
     34 static GType
     35 my_test_get_type (void)
     36 {
     37   static GType test_type = 0;
     38 
     39   if (!test_type) {
     40     static const GTypeInfo test_info = {
     41       sizeof (GTestClass),
     42       NULL,
     43       NULL,
     44       (GClassInitFunc) my_test_class_init,
     45       NULL,
     46       NULL,
     47       sizeof (GTest),
     48       0,
     49       (GInstanceInitFunc) my_test_init,
     50       NULL
     51     };
     52 
     53     test_type = g_type_register_static (G_TYPE_OBJECT, "GTest",
     54         &test_info, 0);
     55   }
     56   return test_type;
     57 }
     58 
     59 static void
     60 my_test_class_init (GTestClass * klass)
     61 {
     62   GObjectClass *gobject_class;
     63 
     64   gobject_class = (GObjectClass *) klass;
     65 
     66   parent_class = g_type_class_ref (G_TYPE_OBJECT);
     67 
     68   gobject_class->dispose = my_test_dispose;
     69 }
     70 
     71 static void
     72 my_test_init (GTest * test)
     73 {
     74   g_print ("init %p\n", test);
     75 }
     76 
     77 static void
     78 my_test_dispose (GObject * object)
     79 {
     80   GTest *test;
     81 
     82   test = MY_TEST (object);
     83 
     84   g_print ("dispose %p!\n", object);
     85 
     86   G_OBJECT_CLASS (parent_class)->dispose (object);
     87 }
     88 
     89 static void
     90 my_test_do_refcount (GTest * test)
     91 {
     92   g_object_ref (test);
     93   g_object_unref (test);
     94 }
     95 
     96 static gpointer
     97 run_thread (GTest * test)
     98 {
     99   gint i = 1;
    100 
    101   while (!stopping) {
    102     my_test_do_refcount (test);
    103     if ((i++ % 10000) == 0) {
    104       g_print (".");
    105       g_thread_yield(); /* force context switch */
    106     }
    107   }
    108 
    109   return NULL;
    110 }
    111 
    112 int
    113 main (int argc, char **argv)
    114 {
    115   gint i;
    116   GTest *test1, *test2;
    117   GArray *test_threads;
    118   const guint n_threads = 5;
    119 
    120   g_thread_init (NULL);
    121   g_print ("START: %s\n", argv[0]);
    122   g_log_set_always_fatal (G_LOG_LEVEL_WARNING | G_LOG_LEVEL_CRITICAL | g_log_set_always_fatal (G_LOG_FATAL_MASK));
    123   g_type_init ();
    124 
    125   test1 = g_object_new (G_TYPE_TEST, NULL);
    126   test2 = g_object_new (G_TYPE_TEST, NULL);
    127 
    128   test_threads = g_array_new (FALSE, FALSE, sizeof (GThread *));
    129 
    130   stopping = FALSE;
    131 
    132   for (i = 0; i < n_threads; i++) {
    133     GThread *thread;
    134 
    135     thread = g_thread_create ((GThreadFunc) run_thread, test1, TRUE, NULL);
    136     g_array_append_val (test_threads, thread);
    137 
    138     thread = g_thread_create ((GThreadFunc) run_thread, test2, TRUE, NULL);
    139     g_array_append_val (test_threads, thread);
    140   }
    141   g_usleep (5000000);
    142 
    143   stopping = TRUE;
    144 
    145   g_print ("\nstopping\n");
    146 
    147   /* join all threads */
    148   for (i = 0; i < 2 * n_threads; i++) {
    149     GThread *thread;
    150 
    151     thread = g_array_index (test_threads, GThread *, i);
    152     g_thread_join (thread);
    153   }
    154 
    155   g_print ("stopped\n");
    156 
    157   return 0;
    158 }
    159