Branch data Line data Source code
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 : 10 : thread_func (gpointer data)
26 : : {
27 : 10 : gint idx = GPOINTER_TO_INT (data);
28 : : gint i;
29 : : gint d;
30 : : gint value;
31 : : gint new_value;
32 : :
33 : 100010 : for (i = 0; i < ROUNDS; i++)
34 : : {
35 : 100000 : d = g_random_int_range (-10, 100);
36 : 100000 : bucket[idx] += d;
37 : 139636 : retry:
38 : 139636 : value = GPOINTER_TO_INT (g_object_get_data (object, "test"));
39 : 139636 : new_value = value + d;
40 : 139636 : if (fail)
41 : 0 : g_object_set_data (object, "test", GINT_TO_POINTER (new_value));
42 : : else
43 : : {
44 : 139636 : if (!g_object_replace_data (object, "test",
45 : 139636 : GINT_TO_POINTER (value),
46 : 139636 : GINT_TO_POINTER (new_value),
47 : : NULL, NULL))
48 : 39636 : goto retry;
49 : : }
50 : 100000 : g_thread_yield ();
51 : : }
52 : :
53 : 10 : return NULL;
54 : : }
55 : :
56 : : static void
57 : 1 : test_qdata_threaded (void)
58 : : {
59 : : gint sum;
60 : : gint i;
61 : : GThread *threads[THREADS];
62 : : gint result;
63 : :
64 : 1 : object = g_object_new (G_TYPE_OBJECT, NULL);
65 : 1 : g_object_set_data (object, "test", GINT_TO_POINTER (0));
66 : :
67 : 11 : for (i = 0; i < THREADS; i++)
68 : 10 : bucket[i] = 0;
69 : :
70 : 11 : for (i = 0; i < THREADS; i++)
71 : 10 : threads[i] = g_thread_new ("qdata", thread_func, GINT_TO_POINTER (i));
72 : :
73 : 11 : for (i = 0; i < THREADS; i++)
74 : 10 : g_thread_join (threads[i]);
75 : :
76 : 1 : sum = 0;
77 : 11 : for (i = 0; i < THREADS; i++)
78 : 10 : sum += bucket[i];
79 : :
80 : 1 : result = GPOINTER_TO_INT (g_object_get_data (object, "test"));
81 : :
82 : 1 : g_assert_cmpint (sum, ==, result);
83 : :
84 : 1 : g_object_unref (object);
85 : 1 : }
86 : :
87 : : static void
88 : 1 : test_qdata_dup (void)
89 : : {
90 : : gchar *s, *s2;
91 : : GQuark quark;
92 : : gboolean b;
93 : :
94 : 1 : quark = g_quark_from_static_string ("test");
95 : 1 : object = g_object_new (G_TYPE_OBJECT, NULL);
96 : 1 : s = g_strdup ("s");
97 : 1 : g_object_set_qdata_full (object, quark, s, g_free);
98 : :
99 : 1 : s2 = g_object_dup_qdata (object, quark, (GDuplicateFunc)g_strdup, NULL);
100 : :
101 : 1 : g_assert_cmpstr (s, ==, s2);
102 : 1 : g_assert (s != s2);
103 : :
104 : 1 : g_free (s2);
105 : :
106 : 1 : b = g_object_replace_qdata (object, quark, s, "s2", NULL, NULL);
107 : 1 : g_assert (b);
108 : :
109 : 1 : g_free (s);
110 : :
111 : 1 : g_object_unref (object);
112 : 1 : }
113 : :
114 : : int
115 : 1 : main (int argc, char **argv)
116 : : {
117 : 1 : g_test_init (&argc, &argv, NULL);
118 : :
119 : 1 : fail = !!g_getenv ("FAIL");
120 : :
121 : 1 : g_test_add_func ("/qdata/threaded", test_qdata_threaded);
122 : 1 : g_test_add_func ("/qdata/dup", test_qdata_dup);
123 : :
124 : 1 : return g_test_run ();
125 : : }
|