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