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
14gboolean fail;
15
16#define THREADS 10
17#define ROUNDS 10000
18
19GObject *object;
20gint bucket[THREADS]; /* accessed from multiple threads, but should never be contested due to the sequence of thread operations */
21
22static gpointer
23thread_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 (begin: -10, end: 100);
34 bucket[idx] += d;
35retry:
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, key: "test", GINT_TO_POINTER (new_value));
40 else
41 {
42 if (!g_object_replace_data (object, key: "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
54static void
55test_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, key: "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 (name: "qdata", func: thread_func, GINT_TO_POINTER (i));
70
71 for (i = 0; i < THREADS; i++)
72 g_thread_join (thread: 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
85static void
86test_qdata_dup (void)
87{
88 gchar *s, *s2;
89 GQuark quark;
90 gboolean b;
91
92 quark = g_quark_from_static_string (string: "test");
93 object = g_object_new (G_TYPE_OBJECT, NULL);
94 s = g_strdup (str: "s");
95 g_object_set_qdata_full (object, quark, data: s, destroy: g_free);
96
97 s2 = g_object_dup_qdata (object, quark, dup_func: (GDuplicateFunc)g_strdup, NULL);
98
99 g_assert_cmpstr (s, ==, s2);
100 g_assert (s != s2);
101
102 g_free (mem: s2);
103
104 b = g_object_replace_qdata (object, quark, oldval: s, newval: "s2", NULL, NULL);
105 g_assert (b);
106
107 g_free (mem: s);
108
109 g_object_unref (object);
110}
111
112int
113main (int argc, char **argv)
114{
115 g_test_init (argc: &argc, argv: &argv, NULL);
116
117 fail = !!g_getenv (variable: "FAIL");
118
119 g_test_add_func (testpath: "/qdata/threaded", test_func: test_qdata_threaded);
120 g_test_add_func (testpath: "/qdata/dup", test_func: test_qdata_dup);
121
122 return g_test_run ();
123}
124

source code of gtk/subprojects/glib/gobject/tests/qdata.c