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 static GRand *rand;
     13 
     14 typedef struct _GTest GTest;
     15 typedef struct _GTestClass GTestClass;
     16 
     17 struct _GTest
     18 {
     19   GObject object;
     20 
     21   gint value;
     22 };
     23 
     24 struct _GTestClass
     25 {
     26   GObjectClass parent_class;
     27 
     28   void (*test_signal1) (GTest * test, gint an_int);
     29   void (*test_signal2) (GTest * test, gint an_int);
     30 };
     31 
     32 static GType my_test_get_type (void);
     33 static volatile gboolean stopping;
     34 
     35 /* Element signals and args */
     36 enum
     37 {
     38   TEST_SIGNAL1,
     39   TEST_SIGNAL2,
     40   /* add more above */
     41   LAST_SIGNAL
     42 };
     43 
     44 enum
     45 {
     46   ARG_0,
     47   ARG_TEST_PROP
     48 };
     49 
     50 static void my_test_class_init (GTestClass * klass);
     51 static void my_test_init (GTest * test);
     52 static void my_test_dispose (GObject * object);
     53 
     54 static void signal2_handler (GTest * test, gint anint);
     55 
     56 static void my_test_set_property (GObject * object, guint prop_id,
     57     const GValue * value, GParamSpec * pspec);
     58 static void my_test_get_property (GObject * object, guint prop_id,
     59     GValue * value, GParamSpec * pspec);
     60 
     61 static GObjectClass *parent_class = NULL;
     62 
     63 static guint my_test_signals[LAST_SIGNAL] = { 0 };
     64 
     65 static GType
     66 my_test_get_type (void)
     67 {
     68   static GType test_type = 0;
     69 
     70   if (!test_type) {
     71     static const GTypeInfo test_info = {
     72       sizeof (GTestClass),
     73       NULL,
     74       NULL,
     75       (GClassInitFunc) my_test_class_init,
     76       NULL,
     77       NULL,
     78       sizeof (GTest),
     79       0,
     80       (GInstanceInitFunc) my_test_init,
     81       NULL
     82     };
     83 
     84     rand = g_rand_new();
     85 
     86     test_type = g_type_register_static (G_TYPE_OBJECT, "GTest",
     87         &test_info, 0);
     88   }
     89   return test_type;
     90 }
     91 
     92 static void
     93 my_test_class_init (GTestClass * klass)
     94 {
     95   GObjectClass *gobject_class;
     96 
     97   gobject_class = (GObjectClass *) klass;
     98 
     99   parent_class = g_type_class_ref (G_TYPE_OBJECT);
    100 
    101   if (!g_thread_supported ())
    102     g_thread_init (NULL);
    103 
    104   gobject_class->dispose = my_test_dispose;
    105   gobject_class->set_property = my_test_set_property;
    106   gobject_class->get_property = my_test_get_property;
    107 
    108   my_test_signals[TEST_SIGNAL1] =
    109       g_signal_new ("test-signal1", G_TYPE_FROM_CLASS (klass),
    110       G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GTestClass, test_signal1), NULL,
    111       NULL, g_cclosure_marshal_VOID__INT, G_TYPE_NONE, 1, G_TYPE_INT);
    112   my_test_signals[TEST_SIGNAL2] =
    113       g_signal_new ("test-signal2", G_TYPE_FROM_CLASS (klass),
    114       G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GTestClass, test_signal2), NULL,
    115       NULL, g_cclosure_marshal_VOID__INT, G_TYPE_NONE, 1, G_TYPE_INT);
    116 
    117   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_TEST_PROP,
    118       g_param_spec_int ("test-prop", "Test Prop", "Test property",
    119           0, 1, 0, G_PARAM_READWRITE));
    120 
    121   klass->test_signal2 = signal2_handler;
    122 }
    123 
    124 static void
    125 my_test_init (GTest * test)
    126 {
    127   g_print ("init %p\n", test);
    128 
    129   test->value = 0;
    130 }
    131 
    132 static void
    133 my_test_dispose (GObject * object)
    134 {
    135   GTest *test;
    136 
    137   test = MY_TEST (object);
    138 
    139   g_print ("dispose %p!\n", object);
    140 
    141   G_OBJECT_CLASS (parent_class)->dispose (object);
    142 }
    143 
    144 static void
    145 my_test_set_property (GObject * object, guint prop_id,
    146                       const GValue * value, GParamSpec * pspec)
    147 {
    148   GTest *test;
    149 
    150   test = MY_TEST (object);
    151 
    152   switch (prop_id) {
    153     case ARG_TEST_PROP:
    154       test->value = g_value_get_int (value);
    155       break;
    156     default:
    157       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
    158       break;
    159   }
    160 }
    161 
    162 static void
    163 my_test_get_property (GObject * object, guint prop_id,
    164                       GValue * value, GParamSpec * pspec)
    165 {
    166   GTest *test;
    167 
    168   test = MY_TEST (object);
    169 
    170   switch (prop_id) {
    171     case ARG_TEST_PROP:
    172       g_value_set_int (value, test->value);
    173       break;
    174     default:
    175       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
    176       break;
    177   }
    178 }
    179 
    180 static void
    181 my_test_do_signal1 (GTest * test)
    182 {
    183   g_signal_emit (G_OBJECT (test), my_test_signals[TEST_SIGNAL1], 0, 0);
    184 }
    185 
    186 static void
    187 signal2_handler (GTest * test, gint anint)
    188 {
    189 }
    190 
    191 static void
    192 my_test_do_signal2 (GTest * test)
    193 {
    194   g_signal_emit (G_OBJECT (test), my_test_signals[TEST_SIGNAL2], 0, 0);
    195 }
    196 
    197 static void
    198 my_test_do_prop (GTest * test)
    199 {
    200   test->value = g_rand_int (rand);
    201   g_object_notify (G_OBJECT (test), "test-prop");
    202 }
    203 
    204 static gpointer
    205 run_thread (GTest * test)
    206 {
    207   gint i = 1;
    208 
    209   while (!stopping) {
    210     if (TESTNUM == 1)
    211       my_test_do_signal1 (test);
    212     if (TESTNUM == 2)
    213       my_test_do_signal2 (test);
    214     if (TESTNUM == 3)
    215       my_test_do_prop (test);
    216     if ((i++ % 10000) == 0) {
    217       g_print (".");
    218       g_thread_yield(); /* force context switch */
    219     }
    220   }
    221 
    222   return NULL;
    223 }
    224 
    225 static void
    226 notify (GObject *object, GParamSpec *spec, gpointer user_data)
    227 {
    228   gint value;
    229 
    230   g_object_get (object, "test-prop", &value, NULL);
    231   /*g_print ("+ %d", value);*/
    232 }
    233 
    234 int
    235 main (int argc, char **argv)
    236 {
    237   gint i;
    238   GTest *test1, *test2;
    239   GArray *test_threads;
    240   const gint n_threads = 1;
    241 
    242   g_thread_init (NULL);
    243   g_print ("START: %s\n", argv[0]);
    244   g_log_set_always_fatal (G_LOG_LEVEL_WARNING | G_LOG_LEVEL_CRITICAL | g_log_set_always_fatal (G_LOG_FATAL_MASK));
    245   g_type_init ();
    246 
    247   test1 = g_object_new (G_TYPE_TEST, NULL);
    248   test2 = g_object_new (G_TYPE_TEST, NULL);
    249 
    250   g_signal_connect (test1, "notify::test-prop", G_CALLBACK (notify), NULL);
    251   g_signal_connect (test1, "test-signal1", G_CALLBACK (notify), NULL);
    252   g_signal_connect (test1, "test-signal2", G_CALLBACK (notify), NULL);
    253 
    254   test_threads = g_array_new (FALSE, FALSE, sizeof (GThread *));
    255 
    256   stopping = FALSE;
    257 
    258   for (i = 0; i < n_threads; i++) {
    259     GThread *thread;
    260 
    261     thread = g_thread_create ((GThreadFunc) run_thread, test1, TRUE, NULL);
    262     g_array_append_val (test_threads, thread);
    263 
    264     thread = g_thread_create ((GThreadFunc) run_thread, test2, TRUE, NULL);
    265     g_array_append_val (test_threads, thread);
    266   }
    267   g_usleep (5000000);
    268 
    269   stopping = TRUE;
    270 
    271   g_print ("\nstopping\n");
    272 
    273   /* join all threads */
    274   for (i = 0; i < 2 * n_threads; i++) {
    275     GThread *thread;
    276 
    277     thread = g_array_index (test_threads, GThread *, i);
    278     g_thread_join (thread);
    279   }
    280 
    281   g_print ("stopped\n");
    282 
    283   return 0;
    284 }
    285