Branch data Line data Source code
1 : : #include <glib.h>
2 : : #include <glib-object.h>
3 : :
4 : : #define G_TYPE_TEST (my_test_get_type ())
5 : : #define MY_TEST(test) (G_TYPE_CHECK_INSTANCE_CAST ((test), G_TYPE_TEST, GTest))
6 : : #define MY_IS_TEST(test) (G_TYPE_CHECK_INSTANCE_TYPE ((test), G_TYPE_TEST))
7 : : #define MY_TEST_CLASS(tclass) (G_TYPE_CHECK_CLASS_CAST ((tclass), G_TYPE_TEST, GTestClass))
8 : : #define MY_IS_TEST_CLASS(tclass) (G_TYPE_CHECK_CLASS_TYPE ((tclass), G_TYPE_TEST))
9 : : #define MY_TEST_GET_CLASS(test) (G_TYPE_INSTANCE_GET_CLASS ((test), G_TYPE_TEST, GTestClass))
10 : :
11 : : enum {
12 : : PROP_0,
13 : : PROP_DUMMY
14 : : };
15 : :
16 : : typedef struct _GTest GTest;
17 : : typedef struct _GTestClass GTestClass;
18 : :
19 : : struct _GTest
20 : : {
21 : : GObject object;
22 : : gint id;
23 : : gint dummy;
24 : :
25 : : gint count;
26 : : gint setcount;
27 : : };
28 : :
29 : : struct _GTestClass
30 : : {
31 : : GObjectClass parent_class;
32 : : };
33 : :
34 : : static GType my_test_get_type (void);
35 : 18850498 : G_DEFINE_TYPE (GTest, my_test, G_TYPE_OBJECT)
36 : :
37 : : static gint stopping; /* (atomic) */
38 : :
39 : : static void my_test_get_property (GObject *object,
40 : : guint prop_id,
41 : : GValue *value,
42 : : GParamSpec *pspec);
43 : : static void my_test_set_property (GObject *object,
44 : : guint prop_id,
45 : : const GValue *value,
46 : : GParamSpec *pspec);
47 : :
48 : : static void
49 : 1 : my_test_class_init (GTestClass * klass)
50 : : {
51 : : GObjectClass *gobject_class;
52 : :
53 : 1 : gobject_class = (GObjectClass *) klass;
54 : :
55 : 1 : gobject_class->get_property = my_test_get_property;
56 : 1 : gobject_class->set_property = my_test_set_property;
57 : :
58 : 1 : g_object_class_install_property (gobject_class,
59 : : PROP_DUMMY,
60 : : g_param_spec_int ("dummy",
61 : : NULL,
62 : : NULL,
63 : : 0, G_MAXINT, 0,
64 : : G_PARAM_READWRITE));
65 : 1 : }
66 : :
67 : : static void
68 : 1 : my_test_init (GTest * test)
69 : : {
70 : : static guint static_id = 1;
71 : 1 : test->id = static_id++;
72 : 1 : }
73 : :
74 : : static void
75 : 8882273 : my_test_get_property (GObject *object,
76 : : guint prop_id,
77 : : GValue *value,
78 : : GParamSpec *pspec)
79 : : {
80 : : GTest *test;
81 : :
82 : 8882273 : test = MY_TEST (object);
83 : :
84 : 8882273 : switch (prop_id)
85 : : {
86 : 8882273 : case PROP_DUMMY:
87 : 8882273 : g_value_set_int (value, g_atomic_int_get (&test->dummy));
88 : 8882273 : break;
89 : 0 : default:
90 : 0 : G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
91 : 0 : break;
92 : : }
93 : 8882273 : }
94 : :
95 : : static void
96 : 8882273 : my_test_set_property (GObject *object,
97 : : guint prop_id,
98 : : const GValue *value,
99 : : GParamSpec *pspec)
100 : : {
101 : : GTest *test;
102 : :
103 : 8882273 : test = MY_TEST (object);
104 : :
105 : 8882273 : switch (prop_id)
106 : : {
107 : 8882273 : case PROP_DUMMY:
108 : 8882273 : g_atomic_int_set (&test->dummy, g_value_get_int (value));
109 : 8882273 : break;
110 : 0 : default:
111 : 0 : G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
112 : 0 : break;
113 : : }
114 : 8882273 : }
115 : :
116 : : static void
117 : 1085949 : dummy_notify (GObject *object,
118 : : GParamSpec *pspec)
119 : : {
120 : : GTest *test;
121 : :
122 : 1085949 : test = MY_TEST (object);
123 : :
124 : 1085949 : g_atomic_int_inc (&test->count);
125 : 1085949 : }
126 : :
127 : : static void
128 : 8882273 : my_test_do_property (GTest * test)
129 : : {
130 : : gint dummy;
131 : :
132 : 8882273 : g_atomic_int_inc (&test->setcount);
133 : :
134 : 8882273 : g_object_get (test, "dummy", &dummy, NULL);
135 : 8882273 : g_object_set (test, "dummy", dummy + 1, NULL);
136 : 8882273 : }
137 : :
138 : : static gpointer
139 : 5 : run_thread (GTest * test)
140 : : {
141 : 5 : gint i = 1;
142 : :
143 : 8882278 : while (!g_atomic_int_get (&stopping)) {
144 : 8882273 : my_test_do_property (test);
145 : 8882273 : if ((i++ % 10000) == 0)
146 : : {
147 : 885 : g_thread_yield(); /* force context switch */
148 : : }
149 : : }
150 : :
151 : 5 : return NULL;
152 : : }
153 : :
154 : : static void
155 : 1 : test_refcount_properties_3 (void)
156 : : {
157 : : gint i;
158 : : GTest *test;
159 : : GArray *test_threads;
160 : 1 : const gint n_threads = 5;
161 : :
162 : 1 : test = g_object_new (G_TYPE_TEST, NULL);
163 : :
164 : 1 : g_assert_cmpint (test->count, ==, test->dummy);
165 : 1 : g_signal_connect (test, "notify::dummy", G_CALLBACK (dummy_notify), NULL);
166 : :
167 : 1 : test_threads = g_array_new (FALSE, FALSE, sizeof (GThread *));
168 : :
169 : 1 : g_atomic_int_set (&stopping, 0);
170 : :
171 : 6 : for (i = 0; i < n_threads; i++) {
172 : : GThread *thread;
173 : :
174 : 5 : thread = g_thread_new (NULL, (GThreadFunc) run_thread, test);
175 : 5 : g_array_append_val (test_threads, thread);
176 : : }
177 : 1 : g_usleep (30000000);
178 : :
179 : 1 : g_atomic_int_set (&stopping, 1);
180 : 1 : g_test_message ("\nstopping\n");
181 : :
182 : : /* join all threads */
183 : 6 : for (i = 0; i < n_threads; i++) {
184 : : GThread *thread;
185 : :
186 : 5 : thread = g_array_index (test_threads, GThread *, i);
187 : 5 : g_thread_join (thread);
188 : : }
189 : :
190 : 1 : g_test_message ("stopped\n");
191 : 1 : g_test_message ("%d %d\n", test->setcount, test->count);
192 : :
193 : 1 : g_array_free (test_threads, TRUE);
194 : 1 : g_object_unref (test);
195 : 1 : }
196 : :
197 : : int
198 : 1 : main (int argc, gchar *argv[])
199 : : {
200 : 1 : g_log_set_always_fatal (G_LOG_LEVEL_WARNING |
201 : 1 : G_LOG_LEVEL_CRITICAL |
202 : 1 : g_log_set_always_fatal (G_LOG_FATAL_MASK));
203 : :
204 : 1 : g_test_init (&argc, &argv, NULL);
205 : :
206 : 1 : g_test_add_func ("/gobject/refcount/properties-3", test_refcount_properties_3);
207 : :
208 : 1 : return g_test_run ();
209 : : }
|