• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* GObject - GLib Type, Object, Parameter and Signal Library
2  * Copyright (C) 2005 Red Hat, Inc.
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General
15  * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
16  */
17 
18 #undef	G_LOG_DOMAIN
19 #define	G_LOG_DOMAIN "TestReferences"
20 
21 #undef G_DISABLE_ASSERT
22 #undef G_DISABLE_CHECKS
23 #undef G_DISABLE_CAST_CHECKS
24 
25 #include	<glib-object.h>
26 
27 /* This test tests weak and toggle references
28  */
29 
30 static GObject *global_object;
31 
32 static gboolean object_destroyed;
33 static gboolean weak_ref1_notified;
34 static gboolean weak_ref2_notified;
35 static gboolean toggle_ref1_weakened;
36 static gboolean toggle_ref1_strengthened;
37 static gboolean toggle_ref2_weakened;
38 static gboolean toggle_ref2_strengthened;
39 static gboolean toggle_ref3_weakened;
40 static gboolean toggle_ref3_strengthened;
41 
42 /*
43  * TestObject, a parent class for TestObject
44  */
45 static GType test_object_get_type (void);
46 #define TEST_TYPE_OBJECT          (test_object_get_type ())
47 typedef struct _TestObject        TestObject;
48 typedef struct _TestObjectClass   TestObjectClass;
49 
50 struct _TestObject
51 {
52   GObject parent_instance;
53 };
54 struct _TestObjectClass
55 {
56   GObjectClass parent_class;
57 };
58 
G_DEFINE_TYPE(TestObject,test_object,G_TYPE_OBJECT)59 G_DEFINE_TYPE (TestObject, test_object, G_TYPE_OBJECT)
60 
61 static void
62 test_object_finalize (GObject *object)
63 {
64   object_destroyed = TRUE;
65 
66   G_OBJECT_CLASS (test_object_parent_class)->finalize (object);
67 }
68 
69 static void
test_object_class_init(TestObjectClass * class)70 test_object_class_init (TestObjectClass *class)
71 {
72   GObjectClass *object_class = G_OBJECT_CLASS (class);
73 
74   object_class->finalize = test_object_finalize;
75 }
76 
77 static void
test_object_init(TestObject * test_object)78 test_object_init (TestObject *test_object)
79 {
80 }
81 
82 static void
clear_flags(void)83 clear_flags (void)
84 {
85   object_destroyed = FALSE;
86   weak_ref1_notified = FALSE;
87   weak_ref2_notified = FALSE;
88   toggle_ref1_weakened = FALSE;
89   toggle_ref1_strengthened = FALSE;
90   toggle_ref2_weakened = FALSE;
91   toggle_ref2_strengthened = FALSE;
92   toggle_ref3_weakened = FALSE;
93   toggle_ref3_strengthened = FALSE;
94 }
95 
96 static void
weak_ref1(gpointer data,GObject * object)97 weak_ref1 (gpointer data,
98 	   GObject *object)
99 {
100   g_assert (object == global_object);
101   g_assert (data == GUINT_TO_POINTER (42));
102 
103   weak_ref1_notified = TRUE;
104 }
105 
106 static void
weak_ref2(gpointer data,GObject * object)107 weak_ref2 (gpointer data,
108 	   GObject *object)
109 {
110   g_assert (object == global_object);
111   g_assert (data == GUINT_TO_POINTER (24));
112 
113   weak_ref2_notified = TRUE;
114 }
115 
116 static void
toggle_ref1(gpointer data,GObject * object,gboolean is_last_ref)117 toggle_ref1 (gpointer data,
118 	     GObject *object,
119 	     gboolean is_last_ref)
120 {
121   g_assert (object == global_object);
122   g_assert (data == GUINT_TO_POINTER (42));
123 
124   if (is_last_ref)
125     toggle_ref1_weakened = TRUE;
126   else
127     toggle_ref1_strengthened = TRUE;
128 }
129 
130 static void
toggle_ref2(gpointer data,GObject * object,gboolean is_last_ref)131 toggle_ref2 (gpointer data,
132 	     GObject *object,
133 	     gboolean is_last_ref)
134 {
135   g_assert (object == global_object);
136   g_assert (data == GUINT_TO_POINTER (24));
137 
138   if (is_last_ref)
139     toggle_ref2_weakened = TRUE;
140   else
141     toggle_ref2_strengthened = TRUE;
142 }
143 
144 static void
toggle_ref3(gpointer data,GObject * object,gboolean is_last_ref)145 toggle_ref3 (gpointer data,
146 	     GObject *object,
147 	     gboolean is_last_ref)
148 {
149   g_assert (object == global_object);
150   g_assert (data == GUINT_TO_POINTER (34));
151 
152   if (is_last_ref)
153     {
154       toggle_ref3_weakened = TRUE;
155       g_object_remove_toggle_ref (object, toggle_ref3, GUINT_TO_POINTER (34));
156     }
157   else
158     toggle_ref3_strengthened = TRUE;
159 }
160 
161 int
main(int argc,char * argv[])162 main (int   argc,
163       char *argv[])
164 {
165   GObject *object;
166 
167   g_log_set_always_fatal (g_log_set_always_fatal (G_LOG_FATAL_MASK) |
168 			  G_LOG_LEVEL_WARNING |
169 			  G_LOG_LEVEL_CRITICAL);
170 
171   /* Test basic weak reference operation
172    */
173   global_object = object = g_object_new (TEST_TYPE_OBJECT, NULL);
174 
175   g_object_weak_ref (object, weak_ref1, GUINT_TO_POINTER (42));
176 
177   clear_flags ();
178   g_object_unref (object);
179   g_assert (weak_ref1_notified == TRUE);
180   g_assert (object_destroyed == TRUE);
181 
182   /* Test two weak references at once
183    */
184   global_object = object = g_object_new (TEST_TYPE_OBJECT, NULL);
185 
186   g_object_weak_ref (object, weak_ref1, GUINT_TO_POINTER (42));
187   g_object_weak_ref (object, weak_ref2, GUINT_TO_POINTER (24));
188 
189   clear_flags ();
190   g_object_unref (object);
191   g_assert (weak_ref1_notified == TRUE);
192   g_assert (weak_ref2_notified == TRUE);
193   g_assert (object_destroyed == TRUE);
194 
195   /* Test remove weak references
196    */
197   global_object = object = g_object_new (TEST_TYPE_OBJECT, NULL);
198 
199   g_object_weak_ref (object, weak_ref1, GUINT_TO_POINTER (42));
200   g_object_weak_ref (object, weak_ref2, GUINT_TO_POINTER (24));
201   g_object_weak_unref (object, weak_ref1, GUINT_TO_POINTER (42));
202 
203   clear_flags ();
204   g_object_unref (object);
205   g_assert (weak_ref1_notified == FALSE);
206   g_assert (weak_ref2_notified == TRUE);
207   g_assert (object_destroyed == TRUE);
208 
209   /* Test basic toggle reference operation
210    */
211   global_object = object = g_object_new (TEST_TYPE_OBJECT, NULL);
212 
213   g_object_add_toggle_ref (object, toggle_ref1, GUINT_TO_POINTER (42));
214 
215   clear_flags ();
216   g_object_unref (object);
217   g_assert (toggle_ref1_weakened == TRUE);
218   g_assert (toggle_ref1_strengthened == FALSE);
219   g_assert (object_destroyed == FALSE);
220 
221   clear_flags ();
222   g_object_ref (object);
223   g_assert (toggle_ref1_weakened == FALSE);
224   g_assert (toggle_ref1_strengthened == TRUE);
225   g_assert (object_destroyed == FALSE);
226 
227   g_object_unref (object);
228 
229   clear_flags ();
230   g_object_remove_toggle_ref (object, toggle_ref1, GUINT_TO_POINTER (42));
231   g_assert (toggle_ref1_weakened == FALSE);
232   g_assert (toggle_ref1_strengthened == FALSE);
233   g_assert (object_destroyed == TRUE);
234 
235   global_object = object = g_object_new (TEST_TYPE_OBJECT, NULL);
236 
237   /* Test two toggle references at once
238    */
239   g_object_add_toggle_ref (object, toggle_ref1, GUINT_TO_POINTER (42));
240   g_object_add_toggle_ref (object, toggle_ref2, GUINT_TO_POINTER (24));
241 
242   clear_flags ();
243   g_object_unref (object);
244   g_assert (toggle_ref1_weakened == FALSE);
245   g_assert (toggle_ref1_strengthened == FALSE);
246   g_assert (toggle_ref2_weakened == FALSE);
247   g_assert (toggle_ref2_strengthened == FALSE);
248   g_assert (object_destroyed == FALSE);
249 
250   clear_flags ();
251   g_object_remove_toggle_ref (object, toggle_ref1, GUINT_TO_POINTER (42));
252   g_assert (toggle_ref1_weakened == FALSE);
253   g_assert (toggle_ref1_strengthened == FALSE);
254   g_assert (toggle_ref2_weakened == TRUE);
255   g_assert (toggle_ref2_strengthened == FALSE);
256   g_assert (object_destroyed == FALSE);
257 
258   clear_flags ();
259   g_object_remove_toggle_ref (object, toggle_ref2, GUINT_TO_POINTER (24));
260   g_assert (toggle_ref1_weakened == FALSE);
261   g_assert (toggle_ref1_strengthened == FALSE);
262   g_assert (toggle_ref2_weakened == FALSE);
263   g_assert (toggle_ref2_strengthened == FALSE);
264   g_assert (object_destroyed == TRUE);
265 
266   /* Test a toggle reference that removes itself
267    */
268   global_object = object = g_object_new (TEST_TYPE_OBJECT, NULL);
269 
270   g_object_add_toggle_ref (object, toggle_ref3, GUINT_TO_POINTER (34));
271 
272   clear_flags ();
273   g_object_unref (object);
274   g_assert (toggle_ref3_weakened == TRUE);
275   g_assert (toggle_ref3_strengthened == FALSE);
276   g_assert (object_destroyed == TRUE);
277 
278   return 0;
279 }
280