c4c165c3446d4b5399fb36139519234e28bc5827
[platform/upstream/glib.git] / tests / refcount / properties.c
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 }