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