(root)/
glib-2.79.0/
gobject/
tests/
qdata.c
       1  /*
       2   * Copyright 2012 Red Hat, Inc.
       3   *
       4   * SPDX-License-Identifier: LGPL-2.1-or-later
       5   *
       6   * This program is free software; you can redistribute it and/or
       7   * modify it under the terms of the GNU Lesser General Public
       8   * License as published by the Free Software Foundation; either
       9   * version 2.1 of the License, or (at your option) any later version.
      10   *
      11   * See the included COPYING file for more information.
      12   */
      13  
      14  #include <glib-object.h>
      15  
      16  gboolean fail;
      17  
      18  #define THREADS 10
      19  #define ROUNDS 10000
      20  
      21  GObject *object;
      22  gint bucket[THREADS];  /* accessed from multiple threads, but should never be contested due to the sequence of thread operations */
      23  
      24  static gpointer
      25  thread_func (gpointer data)
      26  {
      27    gint idx = GPOINTER_TO_INT (data);
      28    gint i;
      29    gint d;
      30    gint value;
      31    gint new_value;
      32  
      33    for (i = 0; i < ROUNDS; i++)
      34      {
      35        d = g_random_int_range (-10, 100);
      36        bucket[idx] += d;
      37  retry:
      38        value = GPOINTER_TO_INT (g_object_get_data (object, "test"));
      39        new_value = value + d;
      40        if (fail)
      41          g_object_set_data (object, "test", GINT_TO_POINTER (new_value));
      42        else
      43          {
      44            if (!g_object_replace_data (object, "test",
      45                                        GINT_TO_POINTER (value),
      46                                        GINT_TO_POINTER (new_value),
      47                                        NULL, NULL))
      48              goto retry;
      49          }
      50        g_thread_yield ();
      51      }
      52  
      53    return NULL;
      54  }
      55  
      56  static void
      57  test_qdata_threaded (void)
      58  {
      59    gint sum;
      60    gint i;
      61    GThread *threads[THREADS];
      62    gint result;
      63  
      64    object = g_object_new (G_TYPE_OBJECT, NULL);
      65    g_object_set_data (object, "test", GINT_TO_POINTER (0));
      66  
      67    for (i = 0; i < THREADS; i++)
      68      bucket[i] = 0;
      69  
      70    for (i = 0; i < THREADS; i++)
      71      threads[i] = g_thread_new ("qdata", thread_func, GINT_TO_POINTER (i));
      72  
      73    for (i = 0; i < THREADS; i++)
      74      g_thread_join (threads[i]);
      75  
      76    sum = 0;
      77    for (i = 0; i < THREADS; i++)
      78      sum += bucket[i];
      79  
      80    result = GPOINTER_TO_INT (g_object_get_data (object, "test"));
      81  
      82    g_assert_cmpint (sum, ==, result);
      83  
      84    g_object_unref (object);
      85  }
      86  
      87  static void
      88  test_qdata_dup (void)
      89  {
      90    gchar *s, *s2;
      91    GQuark quark;
      92    gboolean b;
      93  
      94    quark = g_quark_from_static_string ("test");
      95    object = g_object_new (G_TYPE_OBJECT, NULL);
      96    s = g_strdup ("s");
      97    g_object_set_qdata_full (object, quark, s, g_free);
      98  
      99    s2 = g_object_dup_qdata (object, quark, (GDuplicateFunc)g_strdup, NULL);
     100  
     101    g_assert_cmpstr (s, ==, s2);
     102    g_assert (s != s2);
     103  
     104    g_free (s2);
     105  
     106    b = g_object_replace_qdata (object, quark, s, "s2", NULL, NULL);
     107    g_assert (b);
     108  
     109    g_free (s);
     110  
     111    g_object_unref (object);
     112  }
     113  
     114  int
     115  main (int argc, char **argv)
     116  {
     117    g_test_init (&argc, &argv, NULL);
     118  
     119    fail = !!g_getenv ("FAIL");
     120  
     121    g_test_add_func ("/qdata/threaded", test_qdata_threaded);
     122    g_test_add_func ("/qdata/dup", test_qdata_dup);
     123  
     124    return g_test_run ();
     125  }