Home | History | Annotate | Download | only in gobject
      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 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, write to the
     16  * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
     17  * Boston, MA 02111-1307, USA.
     18  */
     19 
     20 #undef	G_LOG_DOMAIN
     21 #define	G_LOG_DOMAIN "TestReferences"
     22 
     23 #undef G_DISABLE_ASSERT
     24 #undef G_DISABLE_CHECKS
     25 #undef G_DISABLE_CAST_CHECKS
     26 
     27 #include	<glib-object.h>
     28 
     29 /* This test tests weak and toggle references
     30  */
     31 
     32 static GObject *global_object;
     33 
     34 static gboolean object_destroyed;
     35 static gboolean weak_ref1_notified;
     36 static gboolean weak_ref2_notified;
     37 static gboolean toggle_ref1_weakened;
     38 static gboolean toggle_ref1_strengthened;
     39 static gboolean toggle_ref2_weakened;
     40 static gboolean toggle_ref2_strengthened;
     41 static gboolean toggle_ref3_weakened;
     42 static gboolean toggle_ref3_strengthened;
     43 
     44 /*
     45  * TestObject, a parent class for TestObject
     46  */
     47 #define TEST_TYPE_OBJECT          (test_object_get_type ())
     48 typedef struct _TestObject        TestObject;
     49 typedef struct _TestObjectClass   TestObjectClass;
     50 
     51 struct _TestObject
     52 {
     53   GObject parent_instance;
     54 };
     55 struct _TestObjectClass
     56 {
     57   GObjectClass parent_class;
     58 };
     59 
     60 G_DEFINE_TYPE (TestObject, test_object, G_TYPE_OBJECT);
     61 
     62 static void
     63 test_object_finalize (GObject *object)
     64 {
     65   object_destroyed = TRUE;
     66 
     67   G_OBJECT_CLASS (test_object_parent_class)->finalize (object);
     68 }
     69 
     70 static void
     71 test_object_class_init (TestObjectClass *class)
     72 {
     73   GObjectClass *object_class = G_OBJECT_CLASS (class);
     74 
     75   object_class->finalize = test_object_finalize;
     76 }
     77 
     78 static void
     79 test_object_init (TestObject *test_object)
     80 {
     81 }
     82 
     83 static void
     84 clear_flags (void)
     85 {
     86   object_destroyed = FALSE;
     87   weak_ref1_notified = FALSE;
     88   weak_ref2_notified = FALSE;
     89   toggle_ref1_weakened = FALSE;
     90   toggle_ref1_strengthened = FALSE;
     91   toggle_ref2_weakened = FALSE;
     92   toggle_ref2_strengthened = FALSE;
     93   toggle_ref3_weakened = FALSE;
     94   toggle_ref3_strengthened = FALSE;
     95 }
     96 
     97 static void
     98 weak_ref1 (gpointer data,
     99 	   GObject *object)
    100 {
    101   g_assert (object == global_object);
    102   g_assert (data == GUINT_TO_POINTER (42));
    103 
    104   weak_ref1_notified = TRUE;
    105 }
    106 
    107 static void
    108 weak_ref2 (gpointer data,
    109 	   GObject *object)
    110 {
    111   g_assert (object == global_object);
    112   g_assert (data == GUINT_TO_POINTER (24));
    113 
    114   weak_ref2_notified = TRUE;
    115 }
    116 
    117 static void
    118 toggle_ref1 (gpointer data,
    119 	     GObject *object,
    120 	     gboolean is_last_ref)
    121 {
    122   g_assert (object == global_object);
    123   g_assert (data == GUINT_TO_POINTER (42));
    124 
    125   if (is_last_ref)
    126     toggle_ref1_weakened = TRUE;
    127   else
    128     toggle_ref1_strengthened = TRUE;
    129 }
    130 
    131 static void
    132 toggle_ref2 (gpointer data,
    133 	     GObject *object,
    134 	     gboolean is_last_ref)
    135 {
    136   g_assert (object == global_object);
    137   g_assert (data == GUINT_TO_POINTER (24));
    138 
    139   if (is_last_ref)
    140     toggle_ref2_weakened = TRUE;
    141   else
    142     toggle_ref2_strengthened = TRUE;
    143 }
    144 
    145 static void
    146 toggle_ref3 (gpointer data,
    147 	     GObject *object,
    148 	     gboolean is_last_ref)
    149 {
    150   g_assert (object == global_object);
    151   g_assert (data == GUINT_TO_POINTER (34));
    152 
    153   if (is_last_ref)
    154     {
    155       toggle_ref3_weakened = TRUE;
    156       g_object_remove_toggle_ref (object, toggle_ref3, GUINT_TO_POINTER (34));
    157     }
    158   else
    159     toggle_ref3_strengthened = TRUE;
    160 }
    161 
    162 int
    163 main (int   argc,
    164       char *argv[])
    165 {
    166   GObject *object;
    167 
    168   g_log_set_always_fatal (g_log_set_always_fatal (G_LOG_FATAL_MASK) |
    169 			  G_LOG_LEVEL_WARNING |
    170 			  G_LOG_LEVEL_CRITICAL);
    171   g_type_init ();
    172 
    173   /* Test basic weak reference operation
    174    */
    175   global_object = object = g_object_new (TEST_TYPE_OBJECT, NULL);
    176 
    177   g_object_weak_ref (object, weak_ref1, GUINT_TO_POINTER (42));
    178 
    179   clear_flags ();
    180   g_object_unref (object);
    181   g_assert (weak_ref1_notified == TRUE);
    182   g_assert (object_destroyed == TRUE);
    183 
    184   /* Test two weak references at once
    185    */
    186   global_object = object = g_object_new (TEST_TYPE_OBJECT, NULL);
    187 
    188   g_object_weak_ref (object, weak_ref1, GUINT_TO_POINTER (42));
    189   g_object_weak_ref (object, weak_ref2, GUINT_TO_POINTER (24));
    190 
    191   clear_flags ();
    192   g_object_unref (object);
    193   g_assert (weak_ref1_notified == TRUE);
    194   g_assert (weak_ref2_notified == TRUE);
    195   g_assert (object_destroyed == TRUE);
    196 
    197   /* Test remove weak references
    198    */
    199   global_object = object = g_object_new (TEST_TYPE_OBJECT, NULL);
    200 
    201   g_object_weak_ref (object, weak_ref1, GUINT_TO_POINTER (42));
    202   g_object_weak_ref (object, weak_ref2, GUINT_TO_POINTER (24));
    203   g_object_weak_unref (object, weak_ref1, GUINT_TO_POINTER (42));
    204 
    205   clear_flags ();
    206   g_object_unref (object);
    207   g_assert (weak_ref1_notified == FALSE);
    208   g_assert (weak_ref2_notified == TRUE);
    209   g_assert (object_destroyed == TRUE);
    210 
    211   /* Test basic toggle reference operation
    212    */
    213   global_object = object = g_object_new (TEST_TYPE_OBJECT, NULL);
    214 
    215   g_object_add_toggle_ref (object, toggle_ref1, GUINT_TO_POINTER (42));
    216 
    217   clear_flags ();
    218   g_object_unref (object);
    219   g_assert (toggle_ref1_weakened == TRUE);
    220   g_assert (toggle_ref1_strengthened == FALSE);
    221   g_assert (object_destroyed == FALSE);
    222 
    223   clear_flags ();
    224   g_object_ref (object);
    225   g_assert (toggle_ref1_weakened == FALSE);
    226   g_assert (toggle_ref1_strengthened == TRUE);
    227   g_assert (object_destroyed == FALSE);
    228 
    229   g_object_unref (object);
    230 
    231   clear_flags ();
    232   g_object_remove_toggle_ref (object, toggle_ref1, GUINT_TO_POINTER (42));
    233   g_assert (toggle_ref1_weakened == FALSE);
    234   g_assert (toggle_ref1_strengthened == FALSE);
    235   g_assert (object_destroyed == TRUE);
    236 
    237   global_object = object = g_object_new (TEST_TYPE_OBJECT, NULL);
    238 
    239   /* Test two toggle references at once
    240    */
    241   g_object_add_toggle_ref (object, toggle_ref1, GUINT_TO_POINTER (42));
    242   g_object_add_toggle_ref (object, toggle_ref2, GUINT_TO_POINTER (24));
    243 
    244   clear_flags ();
    245   g_object_unref (object);
    246   g_assert (toggle_ref1_weakened == FALSE);
    247   g_assert (toggle_ref1_strengthened == FALSE);
    248   g_assert (toggle_ref2_weakened == FALSE);
    249   g_assert (toggle_ref2_strengthened == FALSE);
    250   g_assert (object_destroyed == FALSE);
    251 
    252   clear_flags ();
    253   g_object_remove_toggle_ref (object, toggle_ref1, GUINT_TO_POINTER (42));
    254   g_assert (toggle_ref1_weakened == FALSE);
    255   g_assert (toggle_ref1_strengthened == FALSE);
    256   g_assert (toggle_ref2_weakened == TRUE);
    257   g_assert (toggle_ref2_strengthened == FALSE);
    258   g_assert (object_destroyed == FALSE);
    259 
    260   clear_flags ();
    261   g_object_remove_toggle_ref (object, toggle_ref2, GUINT_TO_POINTER (24));
    262   g_assert (toggle_ref1_weakened == FALSE);
    263   g_assert (toggle_ref1_strengthened == FALSE);
    264   g_assert (toggle_ref2_weakened == FALSE);
    265   g_assert (toggle_ref2_strengthened == FALSE);
    266   g_assert (object_destroyed == TRUE);
    267 
    268   /* Test a toggle reference that removes itself
    269    */
    270   global_object = object = g_object_new (TEST_TYPE_OBJECT, NULL);
    271 
    272   g_object_add_toggle_ref (object, toggle_ref3, GUINT_TO_POINTER (34));
    273 
    274   clear_flags ();
    275   g_object_unref (object);
    276   g_assert (toggle_ref3_weakened == TRUE);
    277   g_assert (toggle_ref3_strengthened == FALSE);
    278   g_assert (object_destroyed == TRUE);
    279 
    280   return 0;
    281 }
    282