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 enum {
     13   PROP_0,
     14   PROP_DUMMY
     15 };
     16 
     17 typedef struct _GTest GTest;
     18 typedef struct _GTestClass GTestClass;
     19 
     20 struct _GTest
     21 {
     22   GObject object;
     23   gint id;
     24   gint dummy;
     25 
     26   gint count;
     27 };
     28 
     29 struct _GTestClass
     30 {
     31   GObjectClass parent_class;
     32 };
     33 
     34 static GType my_test_get_type (void);
     35 static volatile gboolean stopping;
     36 
     37 static void my_test_class_init (GTestClass * klass);
     38 static void my_test_init (GTest * test);
     39 static void my_test_dispose (GObject * object);
     40 static void my_test_get_property (GObject    *object,
     41                                   guint       prop_id,
     42                                   GValue     *value,
     43                                   GParamSpec *pspec);
     44 static void my_test_set_property (GObject      *object,
     45                                   guint         prop_id,
     46                                   const GValue *value,
     47                                   GParamSpec   *pspec);
     48 
     49 static GObjectClass *parent_class = NULL;
     50 
     51 static GType
     52 my_test_get_type (void)
     53 {
     54   static GType test_type = 0;
     55 
     56   if (!test_type) {
     57     static const GTypeInfo test_info = {
     58       sizeof (GTestClass),
     59       NULL,
     60       NULL,
     61       (GClassInitFunc) my_test_class_init,
     62       NULL,
     63       NULL,
     64       sizeof (GTest),
     65       0,
     66       (GInstanceInitFunc) my_test_init,
     67       NULL
     68     };
     69 
     70     test_type = g_type_register_static (G_TYPE_OBJECT, "GTest", &test_info, 0);
     71   }
     72   return test_type;
     73 }
     74 
     75 static void
     76 my_test_class_init (GTestClass * klass)
     77 {
     78   GObjectClass *gobject_class;
     79 
     80   gobject_class = (GObjectClass *) klass;
     81 
     82   parent_class = g_type_class_ref (G_TYPE_OBJECT);
     83 
     84   gobject_class->dispose = my_test_dispose;
     85   gobject_class->get_property = my_test_get_property;
     86   gobject_class->set_property = my_test_set_property;
     87 
     88   g_object_class_install_property (gobject_class,
     89 				   PROP_DUMMY,
     90 				   g_param_spec_int ("dummy",
     91 						     NULL,
     92 						     NULL,
     93 						     0, G_MAXINT, 0,
     94 						     G_PARAM_READWRITE));
     95 }
     96 
     97 static void
     98 my_test_init (GTest * test)
     99 {
    100   static guint static_id = 1;
    101   test->id = static_id++;
    102 }
    103 
    104 static void
    105 my_test_dispose (GObject * object)
    106 {
    107   GTest *test;
    108 
    109   test = MY_TEST (object);
    110 
    111   G_OBJECT_CLASS (parent_class)->dispose (object);
    112 }
    113 
    114 static void
    115 my_test_get_property (GObject    *object,
    116                       guint       prop_id,
    117                       GValue     *value,
    118                       GParamSpec *pspec)
    119 {
    120   GTest *test;
    121 
    122   test = MY_TEST (object);
    123 
    124   switch (prop_id)
    125     {
    126     case PROP_DUMMY:
    127       g_value_set_int (value, test->dummy);
    128       break;
    129     default:
    130       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
    131       break;
    132     }
    133 }
    134 
    135 static void
    136 my_test_set_property (GObject      *object,
    137                       guint         prop_id,
    138                       const GValue *value,
    139                       GParamSpec   *pspec)
    140 {
    141   GTest *test;
    142 
    143   test = MY_TEST (object);
    144 
    145   switch (prop_id)
    146     {
    147     case PROP_DUMMY:
    148       test->dummy = g_value_get_int (value);
    149       break;
    150     default:
    151       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
    152       break;
    153     }
    154 }
    155 
    156 static void
    157 dummy_notify (GObject    *object,
    158               GParamSpec *pspec)
    159 {
    160   GTest *test;
    161 
    162   test = MY_TEST (object);
    163 
    164   test->count++;
    165 }
    166 
    167 static void
    168 my_test_do_property (GTest * test)
    169 {
    170   gint dummy;
    171 
    172   g_object_get (test, "dummy", &dummy, NULL);
    173   g_object_set (test, "dummy", dummy + 1, NULL);
    174 }
    175 
    176 static gpointer
    177 run_thread (GTest * test)
    178 {
    179   gint i = 1;
    180 
    181   while (!stopping) {
    182     my_test_do_property (test);
    183     if ((i++ % 10000) == 0)
    184       {
    185         g_print (".%c", 'a' + test->id);
    186         g_thread_yield(); /* force context switch */
    187       }
    188   }
    189 
    190   return NULL;
    191 }
    192 
    193 int
    194 main (int argc, char **argv)
    195 {
    196   gint i;
    197   GArray *test_objects;
    198   GArray *test_threads;
    199   const gint n_threads = 5;
    200 
    201   g_thread_init (NULL);
    202   g_print ("START: %s\n", argv[0]);
    203   g_log_set_always_fatal (G_LOG_LEVEL_WARNING | G_LOG_LEVEL_CRITICAL | g_log_set_always_fatal (G_LOG_FATAL_MASK));
    204   g_type_init ();
    205 
    206   test_objects = g_array_new (FALSE, FALSE, sizeof (GTest *));
    207 
    208   for (i = 0; i < n_threads; i++) {
    209     GTest *test;
    210 
    211     test = g_object_new (G_TYPE_TEST, NULL);
    212     g_array_append_val (test_objects, test);
    213 
    214     g_assert (test->count == test->dummy);
    215     g_signal_connect (test, "notify::dummy", G_CALLBACK (dummy_notify), NULL);
    216   }
    217 
    218   test_threads = g_array_new (FALSE, FALSE, sizeof (GThread *));
    219 
    220   stopping = FALSE;
    221 
    222   for (i = 0; i < n_threads; i++) {
    223     GThread *thread;
    224     GTest *test;
    225 
    226     test = g_array_index (test_objects, GTest *, i);
    227 
    228     thread = g_thread_create ((GThreadFunc) run_thread, test, TRUE, NULL);
    229     g_array_append_val (test_threads, thread);
    230   }
    231   g_usleep (3000000);
    232 
    233   stopping = TRUE;
    234   g_print ("\nstopping\n");
    235 
    236   /* join all threads */
    237   for (i = 0; i < n_threads; i++) {
    238     GThread *thread;
    239 
    240     thread = g_array_index (test_threads, GThread *, i);
    241     g_thread_join (thread);
    242   }
    243 
    244   g_print ("stopped\n");
    245 
    246   for (i = 0; i < n_threads; i++) {
    247     GTest *test;
    248 
    249     test = g_array_index (test_objects, GTest *, i);
    250 
    251     g_assert (test->count == test->dummy);
    252   }
    253 
    254   return 0;
    255 }
    256