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