(root)/
glib-2.79.0/
gobject/
tests/
properties-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  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  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", &test_info, 0);
      74    }
      75    return test_type;
      76  }
      77  
      78  static void
      79  my_test_class_init (GTestClass * klass)
      80  {
      81    GObjectClass *gobject_class;
      82  
      83    gobject_class = (GObjectClass *) klass;
      84  
      85    parent_class = g_type_class_ref (G_TYPE_OBJECT);
      86  
      87    gobject_class->dispose = my_test_dispose;
      88    gobject_class->get_property = my_test_get_property;
      89    gobject_class->set_property = my_test_set_property;
      90  
      91    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  }
      99  
     100  static void
     101  my_test_init (GTest * test)
     102  {
     103    static guint static_id = 1;
     104    test->id = static_id++;
     105  }
     106  
     107  static void
     108  my_test_dispose (GObject * object)
     109  {
     110    G_OBJECT_CLASS (parent_class)->dispose (object);
     111  }
     112  
     113  static void
     114  my_test_get_property (GObject    *object,
     115                        guint       prop_id,
     116                        GValue     *value,
     117                        GParamSpec *pspec)
     118  {
     119    GTest *test;
     120  
     121    test = MY_TEST (object);
     122  
     123    switch (prop_id)
     124      {
     125      case PROP_DUMMY:
     126        g_value_set_int (value, test->dummy);
     127        break;
     128      default:
     129        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
     130        break;
     131      }
     132  }
     133  
     134  static void
     135  my_test_set_property (GObject      *object,
     136                        guint         prop_id,
     137                        const GValue *value,
     138                        GParamSpec   *pspec)
     139  {
     140    GTest *test;
     141  
     142    test = MY_TEST (object);
     143  
     144    switch (prop_id)
     145      {
     146      case PROP_DUMMY:
     147        test->dummy = g_value_get_int (value);
     148        break;
     149      default:
     150        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
     151        break;
     152      }
     153  }
     154  
     155  static void
     156  dummy_notify (GObject    *object,
     157                GParamSpec *pspec)
     158  {
     159    GTest *test;
     160  
     161    test = MY_TEST (object);
     162  
     163    test->count++;
     164  }
     165  
     166  static void
     167  my_test_do_property (GTest * test)
     168  {
     169    gint dummy;
     170  
     171    g_object_get (test, "dummy", &dummy, NULL);
     172    g_object_set (test, "dummy", dummy + 1, NULL);
     173  }
     174  
     175  static gpointer
     176  run_thread (GTest * test)
     177  {
     178    gint i = 1;
     179  
     180    while (!g_atomic_int_get (&stopping)) {
     181      my_test_do_property (test);
     182      if ((i++ % 10000) == 0)
     183        {
     184          g_test_message (".%c", 'a' + test->id);
     185          g_thread_yield(); /* force context switch */
     186        }
     187    }
     188  
     189    return NULL;
     190  }
     191  
     192  static void
     193  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    for (i = 0; i < N_THREADS; i++) {
     201      GTest *test;
     202  
     203      test = g_object_new (G_TYPE_TEST, NULL);
     204      test_objects[i] = test;
     205  
     206      g_assert_cmpint (test->count, ==, test->dummy);
     207      g_signal_connect (test, "notify::dummy", G_CALLBACK (dummy_notify), NULL);
     208    }
     209  
     210    g_atomic_int_set (&stopping, FALSE);
     211  
     212    for (i = 0; i < N_THREADS; i++)
     213      test_threads[i] = g_thread_new (NULL, (GThreadFunc) run_thread, test_objects[i]);
     214  
     215    g_usleep (3000000);
     216  
     217    g_atomic_int_set (&stopping, TRUE);
     218  
     219    /* join all threads */
     220    for (i = 0; i < N_THREADS; i++)
     221      g_thread_join (test_threads[i]);
     222  
     223    for (i = 0; i < N_THREADS; i++) {
     224      GTest *test = test_objects[i];
     225  
     226      g_assert_cmpint (test->count, ==, test->dummy);
     227      g_object_unref (test);
     228    }
     229  }
     230  
     231  int
     232  main (int argc, gchar *argv[])
     233  {
     234    g_log_set_always_fatal (G_LOG_LEVEL_WARNING |
     235                            G_LOG_LEVEL_CRITICAL |
     236                            g_log_set_always_fatal (G_LOG_FATAL_MASK));
     237  
     238    g_test_init (&argc, &argv, NULL);
     239  
     240    g_test_add_func ("/gobject/refcount/properties-1", test_refcount_properties_1);
     241  
     242    return g_test_run ();
     243  }