Merge branch 'test-ip_mreq_source-android-only' into 'master'
[glib.git] / glib / tests / rwlock.c
blob1ddc3a03e3b46bc67479de5bc84030926770150e
1 /* Unit tests for GRWLock
2 * Copyright (C) 2011 Red Hat, Inc
3 * Author: Matthias Clasen
5 * This work is provided "as is"; redistribution and modification
6 * in whole or in part, in any medium, physical or electronic is
7 * permitted without restriction.
9 * This work is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 * In no event shall the authors or contributors be liable for any
14 * direct, indirect, incidental, special, exemplary, or consequential
15 * damages (including, but not limited to, procurement of substitute
16 * goods or services; loss of use, data, or profits; or business
17 * interruption) however caused and on any theory of liability, whether
18 * in contract, strict liability, or tort (including negligence or
19 * otherwise) arising in any way out of the use of this software, even
20 * if advised of the possibility of such damage.
23 /* We are testing some deprecated APIs here */
24 #define GLIB_DISABLE_DEPRECATION_WARNINGS
26 #include <glib.h>
28 static void
29 test_rwlock1 (void)
31 GRWLock lock;
33 g_rw_lock_init (&lock);
34 g_rw_lock_writer_lock (&lock);
35 g_rw_lock_writer_unlock (&lock);
36 g_rw_lock_writer_lock (&lock);
37 g_rw_lock_writer_unlock (&lock);
38 g_rw_lock_clear (&lock);
41 static void
42 test_rwlock2 (void)
44 static GRWLock lock;
46 g_rw_lock_writer_lock (&lock);
47 g_rw_lock_writer_unlock (&lock);
48 g_rw_lock_writer_lock (&lock);
49 g_rw_lock_writer_unlock (&lock);
52 static void
53 test_rwlock3 (void)
55 static GRWLock lock;
56 gboolean ret;
58 ret = g_rw_lock_writer_trylock (&lock);
59 g_assert (ret);
60 ret = g_rw_lock_writer_trylock (&lock);
61 g_assert (!ret);
63 g_rw_lock_writer_unlock (&lock);
66 static void
67 test_rwlock4 (void)
69 static GRWLock lock;
71 g_rw_lock_reader_lock (&lock);
72 g_rw_lock_reader_unlock (&lock);
73 g_rw_lock_reader_lock (&lock);
74 g_rw_lock_reader_unlock (&lock);
77 static void
78 test_rwlock5 (void)
80 static GRWLock lock;
81 gboolean ret;
83 ret = g_rw_lock_reader_trylock (&lock);
84 g_assert (ret);
85 ret = g_rw_lock_reader_trylock (&lock);
86 g_assert (ret);
88 g_rw_lock_reader_unlock (&lock);
89 g_rw_lock_reader_unlock (&lock);
92 static void
93 test_rwlock6 (void)
95 static GRWLock lock;
96 gboolean ret;
98 g_rw_lock_writer_lock (&lock);
99 ret = g_rw_lock_reader_trylock (&lock);
100 g_assert (!ret);
101 g_rw_lock_writer_unlock (&lock);
103 g_rw_lock_reader_lock (&lock);
104 ret = g_rw_lock_writer_trylock (&lock);
105 g_assert (!ret);
106 g_rw_lock_reader_unlock (&lock);
110 #define LOCKS 48
111 #define ITERATIONS 10000
112 #define THREADS 100
115 GThread *owners[LOCKS];
116 GRWLock locks[LOCKS];
118 static void
119 acquire (gint nr)
121 GThread *self;
123 self = g_thread_self ();
125 if (!g_rw_lock_writer_trylock (&locks[nr]))
127 if (g_test_verbose ())
128 g_printerr ("thread %p going to block on lock %d\n", self, nr);
130 g_rw_lock_writer_lock (&locks[nr]);
133 g_assert (owners[nr] == NULL); /* hopefully nobody else is here */
134 owners[nr] = self;
136 /* let some other threads try to ruin our day */
137 g_thread_yield ();
138 g_thread_yield ();
139 g_thread_yield ();
141 g_assert (owners[nr] == self); /* hopefully this is still us... */
142 owners[nr] = NULL; /* make way for the next guy */
144 g_rw_lock_writer_unlock (&locks[nr]);
147 static gpointer
148 thread_func (gpointer data)
150 gint i;
151 GRand *rand;
153 rand = g_rand_new ();
155 for (i = 0; i < ITERATIONS; i++)
156 acquire (g_rand_int_range (rand, 0, LOCKS));
158 g_rand_free (rand);
160 return NULL;
163 static void
164 test_rwlock7 (void)
166 gint i;
167 GThread *threads[THREADS];
169 for (i = 0; i < LOCKS; i++)
170 g_rw_lock_init (&locks[i]);
172 for (i = 0; i < THREADS; i++)
173 threads[i] = g_thread_new ("test", thread_func, NULL);
175 for (i = 0; i < THREADS; i++)
176 g_thread_join (threads[i]);
178 for (i = 0; i < LOCKS; i++)
179 g_rw_lock_clear (&locks[i]);
181 for (i = 0; i < LOCKS; i++)
182 g_assert (owners[i] == NULL);
185 static gint even;
186 static GRWLock even_lock;
187 GThread *writers[2];
188 GThread *readers[10];
190 static void
191 change_even (gpointer data)
193 g_rw_lock_writer_lock (&even_lock);
195 g_assert (even % 2 == 0);
197 even += 1;
199 if (GPOINTER_TO_INT (data) == 0)
200 even += 1;
201 else
202 even -= 1;
204 g_assert (even % 2 == 0);
206 g_rw_lock_writer_unlock (&even_lock);
209 static void
210 verify_even (gpointer data)
212 g_rw_lock_reader_lock (&even_lock);
214 g_assert (even % 2 == 0);
216 g_rw_lock_reader_unlock (&even_lock);
219 static gpointer
220 writer_func (gpointer data)
222 gint i;
224 for (i = 0; i < 100000; i++)
225 change_even (data);
227 return NULL;
230 static gpointer
231 reader_func (gpointer data)
233 gint i;
235 for (i = 0; i < 100000; i++)
236 verify_even (data);
238 return NULL;
241 /* This test has 2 writers and 10 readers.
242 * The writers modify an integer multiple times,
243 * but always leave it with an even value.
244 * The readers verify that they can only observe
245 * even values
247 static void
248 test_rwlock8 (void)
250 gint i;
252 even = 0;
253 g_rw_lock_init (&even_lock);
255 for (i = 0; i < 2; i++)
256 writers[i] = g_thread_new ("a", writer_func, GINT_TO_POINTER (i));
258 for (i = 0; i < 10; i++)
259 readers[i] = g_thread_new ("b", reader_func, NULL);
261 for (i = 0; i < 2; i++)
262 g_thread_join (writers[i]);
264 for (i = 0; i < 10; i++)
265 g_thread_join (readers[i]);
267 g_assert (even % 2 == 0);
269 g_rw_lock_clear (&even_lock);
273 main (int argc, char *argv[])
275 g_test_init (&argc, &argv, NULL);
277 g_test_add_func ("/thread/rwlock1", test_rwlock1);
278 g_test_add_func ("/thread/rwlock2", test_rwlock2);
279 g_test_add_func ("/thread/rwlock3", test_rwlock3);
280 g_test_add_func ("/thread/rwlock4", test_rwlock4);
281 g_test_add_func ("/thread/rwlock5", test_rwlock5);
282 g_test_add_func ("/thread/rwlock6", test_rwlock6);
283 g_test_add_func ("/thread/rwlock7", test_rwlock7);
284 g_test_add_func ("/thread/rwlock8", test_rwlock8);
286 return g_test_run ();