gkdbus: Fix underflow and unreachable code bug
[platform/upstream/glib.git] / gobject / tests / objects-refcount1.c
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 typedef struct _GTest GTest;
16 typedef struct _GTestClass GTestClass;
17
18 #if G_GNUC_CHECK_VERSION (4, 0)
19 /* Increase the alignment of GTest to check whether
20  * G_TYPE_CHECK_INSTANCE_CAST() would trigger a "-Wcast-align=strict" warning.
21  * That would happen, when trying to cast a "GObject*" to "GTest*", if latter
22  * has larger alignment.
23  *
24  * Note that merely adding a int64 field to GTest does not increase the
25  * alignment above 4 bytes on i386, hence use the __attribute__((__aligned__())).
26  */
27 #define _GTest_increase_alignment __attribute__((__aligned__(__alignof(gint64))))
28 #else
29 #define _GTest_increase_alignment
30 #endif
31
32 struct _GTest
33 {
34   GObject object;
35
36   /* See _GTest_increase_alignment. */
37   long double increase_alignment2;
38 } _GTest_increase_alignment;
39
40 struct _GTestClass
41 {
42   GObjectClass parent_class;
43 };
44
45 static GType my_test_get_type (void);
46 static gint stopping;  /* (atomic) */
47
48 static void my_test_class_init (GTestClass * klass);
49 static void my_test_init (GTest * test);
50 static void my_test_dispose (GObject * object);
51
52 static GObjectClass *parent_class = NULL;
53
54 static GType
55 my_test_get_type (void)
56 {
57   static GType test_type = 0;
58
59   if (!test_type) {
60     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     test_type = g_type_register_static (G_TYPE_OBJECT, "GTest",
74         &test_info, 0);
75   }
76   return test_type;
77 }
78
79 static void
80 my_test_class_init (GTestClass * klass)
81 {
82   GObjectClass *gobject_class;
83
84   gobject_class = (GObjectClass *) klass;
85   parent_class = g_type_class_ref (G_TYPE_OBJECT);
86
87   gobject_class->dispose = my_test_dispose;
88 }
89
90 static void
91 my_test_init (GTest * test)
92 {
93   g_test_message ("init %p\n", test);
94 }
95
96 static void
97 my_test_dispose (GObject * object)
98 {
99   GTest *test;
100
101   test = MY_TEST (object);
102
103   g_test_message ("dispose %p!\n", test);
104
105   G_OBJECT_CLASS (parent_class)->dispose (object);
106 }
107
108 static void
109 my_test_do_refcount (GTest * test)
110 {
111   g_object_ref (test);
112   g_object_unref (test);
113 }
114
115 static gpointer
116 run_thread (GTest * test)
117 {
118   gint i = 1;
119
120   while (!g_atomic_int_get (&stopping)) {
121     my_test_do_refcount (test);
122     if ((i++ % 10000) == 0) {
123         g_thread_yield (); /* force context switch */
124     }
125   }
126
127   return NULL;
128 }
129
130 static void
131 test_refcount_object_basics (void)
132 {
133   guint i;
134   GTest *test1, *test2;
135   GArray *test_threads;
136   const guint n_threads = 5;
137
138   test1 = g_object_new (G_TYPE_TEST, NULL);
139   test2 = g_object_new (G_TYPE_TEST, NULL);
140
141   test_threads = g_array_new (FALSE, FALSE, sizeof (GThread *));
142
143   g_atomic_int_set (&stopping, 0);
144
145   for (i = 0; i < n_threads; i++) {
146     GThread *thread;
147
148     thread = g_thread_new (NULL, (GThreadFunc) run_thread, test1);
149     g_array_append_val (test_threads, thread);
150
151     thread = g_thread_new (NULL, (GThreadFunc) run_thread, test2);
152     g_array_append_val (test_threads, thread);
153   }
154
155   g_usleep (5000000);
156   g_atomic_int_set (&stopping, 1);
157
158   /* join all threads */
159   for (i = 0; i < 2 * n_threads; i++) {
160     GThread *thread;
161
162     thread = g_array_index (test_threads, GThread *, i);
163     g_thread_join (thread);
164   }
165
166   g_object_unref (test1);
167   g_object_unref (test2);
168   g_array_unref (test_threads);
169 }
170
171 int
172 main (int argc, gchar *argv[])
173 {
174   g_log_set_always_fatal (G_LOG_LEVEL_WARNING |
175                           G_LOG_LEVEL_CRITICAL |
176                           g_log_set_always_fatal (G_LOG_FATAL_MASK));
177
178   g_test_init (&argc, &argv, NULL);
179
180   g_test_add_func ("/gobject/refcount/object-basics", test_refcount_object_basics);
181
182   return g_test_run ();
183 }