Branch data Line data Source code
1 : : /* GLIB - Library of useful routines for C programming
2 : : * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
3 : : *
4 : : * gthread.c: MT safety related functions
5 : : * Copyright 1998 Sebastian Wilhelmi; University of Karlsruhe
6 : : * Owen Taylor
7 : : *
8 : : * SPDX-License-Identifier: LGPL-2.1-or-later
9 : : *
10 : : * This library is free software; you can redistribute it and/or
11 : : * modify it under the terms of the GNU Lesser General Public
12 : : * License as published by the Free Software Foundation; either
13 : : * version 2.1 of the License, or (at your option) any later version.
14 : : *
15 : : * This library is distributed in the hope that it will be useful,
16 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 : : * Lesser General Public License for more details.
19 : : *
20 : : * You should have received a copy of the GNU Lesser General Public
21 : : * License along with this library; if not, see <http://www.gnu.org/licenses/>.
22 : : */
23 : :
24 : : #include "config.h"
25 : :
26 : : /* we know we are deprecated here, no need for warnings */
27 : : #ifndef GLIB_DISABLE_DEPRECATION_WARNINGS
28 : : #define GLIB_DISABLE_DEPRECATION_WARNINGS
29 : : #endif
30 : :
31 : : #include "gmessages.h"
32 : : #include "gslice.h"
33 : : #include "gmain.h"
34 : : #include "gthread.h"
35 : : #include "gthreadprivate.h"
36 : : #include "deprecated/gthread.h"
37 : : #include "garray.h"
38 : :
39 : : #include "gutils.h"
40 : :
41 : : /* {{{1 Documentation */
42 : :
43 : : /**
44 : : * GThreadPriority: (skip):
45 : : * @G_THREAD_PRIORITY_LOW: a priority lower than normal
46 : : * @G_THREAD_PRIORITY_NORMAL: the default priority
47 : : * @G_THREAD_PRIORITY_HIGH: a priority higher than normal
48 : : * @G_THREAD_PRIORITY_URGENT: the highest priority
49 : : *
50 : : * Thread priorities.
51 : : *
52 : : * Deprecated:2.32: Thread priorities no longer have any effect.
53 : : */
54 : :
55 : : /**
56 : : * GThreadFunctions: (skip):
57 : : * @mutex_new: virtual function pointer for g_mutex_new()
58 : : * @mutex_lock: virtual function pointer for g_mutex_lock()
59 : : * @mutex_trylock: virtual function pointer for g_mutex_trylock()
60 : : * @mutex_unlock: virtual function pointer for g_mutex_unlock()
61 : : * @mutex_free: virtual function pointer for g_mutex_free()
62 : : * @cond_new: virtual function pointer for g_cond_new()
63 : : * @cond_signal: virtual function pointer for g_cond_signal()
64 : : * @cond_broadcast: virtual function pointer for g_cond_broadcast()
65 : : * @cond_wait: virtual function pointer for g_cond_wait()
66 : : * @cond_timed_wait: virtual function pointer for g_cond_timed_wait()
67 : : * @cond_free: virtual function pointer for g_cond_free()
68 : : * @private_new: virtual function pointer for g_private_new()
69 : : * @private_get: virtual function pointer for g_private_get()
70 : : * @private_set: virtual function pointer for g_private_set()
71 : : * @thread_create: virtual function pointer for g_thread_create()
72 : : * @thread_yield: virtual function pointer for g_thread_yield()
73 : : * @thread_join: virtual function pointer for g_thread_join()
74 : : * @thread_exit: virtual function pointer for g_thread_exit()
75 : : * @thread_set_priority: virtual function pointer for
76 : : * g_thread_set_priority()
77 : : * @thread_self: virtual function pointer for g_thread_self()
78 : : * @thread_equal: used internally by recursive mutex locks and by some
79 : : * assertion checks
80 : : *
81 : : * This function table is no longer used by g_thread_init()
82 : : * to initialize the thread system.
83 : : */
84 : :
85 : : /**
86 : : * G_THREADS_IMPL_POSIX: (skip):
87 : : *
88 : : * This macro is defined if POSIX style threads are used.
89 : : *
90 : : * Deprecated:2.32:POSIX threads are in use on all non-Windows systems.
91 : : * Use %G_OS_WIN32 to detect Windows.
92 : : */
93 : :
94 : : /**
95 : : * G_THREADS_IMPL_WIN32: (skip):
96 : : *
97 : : * This macro is defined if Windows style threads are used.
98 : : *
99 : : * Deprecated:2.32:Use %G_OS_WIN32 to detect Windows.
100 : : */
101 : :
102 : :
103 : : /* {{{1 Exported Variables */
104 : :
105 : : /* Set this FALSE to have previously-compiled GStaticMutex code use the
106 : : * slow path (ie: call into us) to avoid compatibility problems.
107 : : */
108 : : gboolean g_thread_use_default_impl = FALSE;
109 : :
110 : : GThreadFunctions g_thread_functions_for_glib_use =
111 : : {
112 : : g_mutex_new,
113 : : g_mutex_lock,
114 : : g_mutex_trylock,
115 : : g_mutex_unlock,
116 : : g_mutex_free,
117 : : g_cond_new,
118 : : g_cond_signal,
119 : : g_cond_broadcast,
120 : : g_cond_wait,
121 : : g_cond_timed_wait,
122 : : g_cond_free,
123 : : g_private_new,
124 : : g_private_get,
125 : : g_private_set,
126 : : NULL,
127 : : g_thread_yield,
128 : : NULL,
129 : : NULL,
130 : : NULL,
131 : : NULL,
132 : : NULL,
133 : : };
134 : :
135 : : static guint64
136 : 0 : gettime (void)
137 : : {
138 : 0 : return g_get_monotonic_time () * 1000;
139 : : }
140 : :
141 : : guint64 (*g_thread_gettime) (void) = gettime;
142 : :
143 : : /* Initialisation {{{1 ---------------------------------------------------- */
144 : : gboolean g_threads_got_initialized = TRUE;
145 : :
146 : : /**
147 : : * g_thread_init: (skip):
148 : : * @vtable: a function table of type #GThreadFunctions, that provides
149 : : * the entry points to the thread system to be used. Since 2.32,
150 : : * this parameter is ignored and should always be %NULL
151 : : *
152 : : * If you use GLib from more than one thread, you must initialize the
153 : : * thread system by calling g_thread_init().
154 : : *
155 : : * Since version 2.24, calling g_thread_init() multiple times is allowed,
156 : : * but nothing happens except for the first call.
157 : : *
158 : : * Since version 2.32, GLib does not support custom thread implementations
159 : : * anymore and the @vtable parameter is ignored and you should pass %NULL.
160 : : *
161 : : * <note><para>g_thread_init() must not be called directly or indirectly
162 : : * in a callback from GLib. Also no mutexes may be currently locked while
163 : : * calling g_thread_init().</para></note>
164 : : *
165 : : * <note><para>To use g_thread_init() in your program, you have to link
166 : : * with the libraries that the command <command>pkg-config --libs
167 : : * gthread-2.0</command> outputs. This is not the case for all the
168 : : * other thread-related functions of GLib. Those can be used without
169 : : * having to link with the thread libraries.</para></note>
170 : : *
171 : : * Deprecated:2.32: This function is no longer necessary. The GLib
172 : : * threading system is automatically initialized at the start
173 : : * of your program.
174 : : */
175 : :
176 : : /**
177 : : * g_thread_init_with_errorcheck_mutexes: (skip):
178 : : */
179 : :
180 : : /**
181 : : * g_thread_get_initialized: (skip):
182 : : *
183 : : * Indicates if g_thread_init() has been called.
184 : : *
185 : : * Returns: %TRUE if threads have been initialized.
186 : : *
187 : : * Since: 2.20
188 : : */
189 : : gboolean
190 : 0 : g_thread_get_initialized (void)
191 : : {
192 : 0 : return g_thread_supported ();
193 : : }
194 : :
195 : : /* We need this for ABI compatibility */
196 : : GLIB_AVAILABLE_IN_ALL
197 : : void g_thread_init_glib (void);
198 : 0 : void g_thread_init_glib (void) { }
199 : :
200 : : /* Internal variables {{{1 */
201 : :
202 : : static GSList *g_thread_all_threads = NULL;
203 : : static GSList *g_thread_free_indices = NULL;
204 : :
205 : : /* Protects g_thread_all_threads and g_thread_free_indices */
206 : : G_LOCK_DEFINE_STATIC (g_static_mutex);
207 : : G_LOCK_DEFINE_STATIC (g_thread);
208 : :
209 : : /* Misc. GThread functions {{{1 */
210 : :
211 : : /**
212 : : * g_thread_set_priority: (skip):
213 : : * @thread: a #GThread.
214 : : * @priority: ignored
215 : : *
216 : : * This function does nothing.
217 : : *
218 : : * Deprecated:2.32: Thread priorities no longer have any effect.
219 : : */
220 : : void
221 : 0 : g_thread_set_priority (GThread *thread,
222 : : GThreadPriority priority)
223 : : {
224 : 0 : }
225 : :
226 : : /**
227 : : * g_thread_foreach: (skip):
228 : : * @thread_func: (scope call): function to call for all #GThread structures
229 : : * @user_data: second argument to @thread_func
230 : : *
231 : : * Call @thread_func on all #GThreads that have been
232 : : * created with g_thread_create().
233 : : *
234 : : * Note that threads may decide to exit while @thread_func is
235 : : * running, so without intimate knowledge about the lifetime of
236 : : * foreign threads, @thread_func shouldn't access the GThread*
237 : : * pointer passed in as first argument. However, @thread_func will
238 : : * not be called for threads which are known to have exited already.
239 : : *
240 : : * Due to thread lifetime checks, this function has an execution complexity
241 : : * which is quadratic in the number of existing threads.
242 : : *
243 : : * Since: 2.10
244 : : *
245 : : * Deprecated:2.32: There aren't many things you can do with a #GThread,
246 : : * except comparing it with one that was returned from g_thread_create().
247 : : * There are better ways to find out if your thread is still alive.
248 : : */
249 : : void
250 : 0 : g_thread_foreach (GFunc thread_func,
251 : : gpointer user_data)
252 : : {
253 : 0 : GSList *slist = NULL;
254 : : GRealThread *thread;
255 : 0 : g_return_if_fail (thread_func != NULL);
256 : : /* snapshot the list of threads for iteration */
257 : 0 : G_LOCK (g_thread);
258 : 0 : slist = g_slist_copy (g_thread_all_threads);
259 : 0 : G_UNLOCK (g_thread);
260 : : /* walk the list, skipping non-existent threads */
261 [ # # ]: 0 : while (slist)
262 : : {
263 : 0 : GSList *node = slist;
264 : 0 : slist = node->next;
265 : : /* check whether the current thread still exists */
266 : 0 : G_LOCK (g_thread);
267 [ # # ]: 0 : if (g_slist_find (g_thread_all_threads, node->data))
268 : 0 : thread = node->data;
269 : : else
270 : 0 : thread = NULL;
271 : 0 : G_UNLOCK (g_thread);
272 [ # # ]: 0 : if (thread)
273 : 0 : thread_func (thread, user_data);
274 : 0 : g_slist_free_1 (node);
275 : : }
276 : : }
277 : :
278 : : static void
279 : 7278 : g_enumerable_thread_remove (gpointer data)
280 : : {
281 : 7278 : GRealThread *thread = data;
282 : :
283 : 7278 : G_LOCK (g_thread);
284 : 7278 : g_thread_all_threads = g_slist_remove (g_thread_all_threads, thread);
285 : 7278 : G_UNLOCK (g_thread);
286 : 7278 : }
287 : :
288 : : GPrivate enumerable_thread_private = G_PRIVATE_INIT (g_enumerable_thread_remove);
289 : :
290 : : static void
291 : 7278 : g_enumerable_thread_add (GRealThread *thread)
292 : : {
293 : 7278 : G_LOCK (g_thread);
294 : 7278 : g_thread_all_threads = g_slist_prepend (g_thread_all_threads, thread);
295 : 7278 : G_UNLOCK (g_thread);
296 : :
297 : 7278 : g_private_set (&enumerable_thread_private, thread);
298 : 7278 : }
299 : :
300 : : static gpointer
301 : 7278 : g_deprecated_thread_proxy (gpointer data)
302 : : {
303 : 7278 : GRealThread *real = data;
304 : :
305 : 7278 : g_enumerable_thread_add (real);
306 : :
307 : 7278 : return g_thread_proxy (data);
308 : : }
309 : :
310 : : /**
311 : : * g_thread_create: (skip):
312 : : * @func: a function to execute in the new thread
313 : : * @data: an argument to supply to the new thread
314 : : * @joinable: should this thread be joinable?
315 : : * @error: return location for error, or %NULL
316 : : *
317 : : * This function creates a new thread.
318 : : *
319 : : * The new thread executes the function @func with the argument @data.
320 : : * If the thread was created successfully, it is returned.
321 : : *
322 : : * @error can be %NULL to ignore errors, or non-%NULL to report errors.
323 : : * The error is set, if and only if the function returns %NULL.
324 : : *
325 : : * This function returns a reference to the created thread only if
326 : : * @joinable is %TRUE. In that case, you must free this reference by
327 : : * calling g_thread_unref() or g_thread_join(). If @joinable is %FALSE
328 : : * then you should probably not touch the return value.
329 : : *
330 : : * Returns: the new #GThread on success
331 : : *
332 : : * Deprecated:2.32: Use g_thread_new() instead
333 : : */
334 : : GThread *
335 : 7278 : g_thread_create (GThreadFunc func,
336 : : gpointer data,
337 : : gboolean joinable,
338 : : GError **error)
339 : : {
340 : 7278 : return g_thread_create_full (func, data, 0, joinable, 0, 0, error);
341 : : }
342 : :
343 : : /**
344 : : * g_thread_create_full: (skip):
345 : : * @func: a function to execute in the new thread.
346 : : * @data: an argument to supply to the new thread.
347 : : * @stack_size: a stack size for the new thread.
348 : : * @joinable: should this thread be joinable?
349 : : * @bound: ignored
350 : : * @priority: ignored
351 : : * @error: return location for error.
352 : : *
353 : : * This function creates a new thread.
354 : : *
355 : : * Returns: the new #GThread on success.
356 : : *
357 : : * Deprecated:2.32: The @bound and @priority arguments are now ignored.
358 : : * Use g_thread_new().
359 : : */
360 : : GThread *
361 : 7278 : g_thread_create_full (GThreadFunc func,
362 : : gpointer data,
363 : : gulong stack_size,
364 : : gboolean joinable,
365 : : gboolean bound,
366 : : GThreadPriority priority,
367 : : GError **error)
368 : : {
369 : : GThread *thread;
370 : :
371 : 7278 : thread = g_thread_new_internal (NULL, g_deprecated_thread_proxy,
372 : : func, data, stack_size, error);
373 : :
374 [ + - - + ]: 7278 : if (thread && !joinable)
375 : : {
376 : 0 : thread->joinable = FALSE;
377 : 0 : g_thread_unref (thread);
378 : : }
379 : :
380 : 7278 : return thread;
381 : : }
382 : :
383 : : /* GOnce {{{1 ------------------------------------------------------------- */
384 : : gboolean
385 : 0 : g_once_init_enter_impl (volatile gsize *location)
386 : : {
387 : 0 : return (g_once_init_enter) (location);
388 : : }
389 : :
390 : : /* GStaticMutex {{{1 ------------------------------------------------------ */
391 : :
392 : : /**
393 : : * GStaticMutex: (skip):
394 : : *
395 : : * A #GStaticMutex works like a #GMutex.
396 : : *
397 : : * Prior to GLib 2.32, GStaticMutex had the significant advantage
398 : : * that it doesn't need to be created at run-time, but can be defined
399 : : * at compile-time. Since 2.32, #GMutex can be statically allocated
400 : : * as well, and GStaticMutex has been deprecated.
401 : : *
402 : : * Here is a version of our give_me_next_number() example using
403 : : * a GStaticMutex:
404 : : * |[
405 : : * int
406 : : * give_me_next_number (void)
407 : : * {
408 : : * static int current_number = 0;
409 : : * int ret_val;
410 : : * static GStaticMutex mutex = G_STATIC_MUTEX_INIT;
411 : : *
412 : : * g_static_mutex_lock (&mutex);
413 : : * ret_val = current_number = calc_next_number (current_number);
414 : : * g_static_mutex_unlock (&mutex);
415 : : *
416 : : * return ret_val;
417 : : * }
418 : : * ]|
419 : : *
420 : : * Sometimes you would like to dynamically create a mutex. If you don't
421 : : * want to require prior calling to g_thread_init(), because your code
422 : : * should also be usable in non-threaded programs, you are not able to
423 : : * use g_mutex_new() and thus #GMutex, as that requires a prior call to
424 : : * g_thread_init(). In these cases you can also use a #GStaticMutex.
425 : : * It must be initialized with g_static_mutex_init() before using it
426 : : * and freed with with g_static_mutex_free() when not needed anymore to
427 : : * free up any allocated resources.
428 : : *
429 : : * Even though #GStaticMutex is not opaque, it should only be used with
430 : : * the following functions, as it is defined differently on different
431 : : * platforms.
432 : : *
433 : : * All of the g_static_mutex_* functions apart from
434 : : * g_static_mutex_get_mutex() can also be used even if g_thread_init()
435 : : * has not yet been called. Then they do nothing, apart from
436 : : * g_static_mutex_trylock() which does nothing but returning %TRUE.
437 : : *
438 : : * All of the g_static_mutex_* functions are actually macros. Apart from
439 : : * taking their addresses, you can however use them as if they were
440 : : * functions.
441 : : */
442 : :
443 : : /**
444 : : * G_STATIC_MUTEX_INIT: (skip):
445 : : *
446 : : * A #GStaticMutex must be initialized with this macro, before it can
447 : : * be used. This macro can used be to initialize a variable, but it
448 : : * cannot be assigned to a variable. In that case you have to use
449 : : * g_static_mutex_init().
450 : : *
451 : : * |[
452 : : * GStaticMutex my_mutex = G_STATIC_MUTEX_INIT;
453 : : * ]|
454 : : **/
455 : :
456 : : /**
457 : : * g_static_mutex_init: (skip):
458 : : * @mutex: a #GStaticMutex to be initialized.
459 : : *
460 : : * Initializes @mutex.
461 : : * Alternatively you can initialize it with %G_STATIC_MUTEX_INIT.
462 : : *
463 : : * Deprecated: 2.32: Use g_mutex_init()
464 : : */
465 : : void
466 : 0 : g_static_mutex_init (GStaticMutex *mutex)
467 : : {
468 : : static const GStaticMutex init_mutex = G_STATIC_MUTEX_INIT;
469 : :
470 : 0 : g_return_if_fail (mutex);
471 : :
472 : 0 : *mutex = init_mutex;
473 : : }
474 : :
475 : : /* IMPLEMENTATION NOTE:
476 : : *
477 : : * On some platforms a GStaticMutex is actually a normal GMutex stored
478 : : * inside of a structure instead of being allocated dynamically. We can
479 : : * only do this for platforms on which we know, in advance, how to
480 : : * allocate (size) and initialise (value) that memory.
481 : : *
482 : : * On other platforms, a GStaticMutex is nothing more than a pointer to
483 : : * a GMutex. In that case, the first access we make to the static mutex
484 : : * must first allocate the normal GMutex and store it into the pointer.
485 : : *
486 : : * configure.ac writes macros into glibconfig.h to determine if
487 : : * g_static_mutex_get_mutex() accesses the structure in memory directly
488 : : * (on platforms where we are able to do that) or if it ends up here,
489 : : * where we may have to allocate the GMutex before returning it.
490 : : */
491 : :
492 : : /**
493 : : * g_static_mutex_get_mutex: (skip):
494 : : * @mutex: a #GStaticMutex.
495 : : *
496 : : * For some operations (like g_cond_wait()) you must have a #GMutex
497 : : * instead of a #GStaticMutex. This function will return the
498 : : * corresponding #GMutex for @mutex.
499 : : *
500 : : * Returns: the #GMutex corresponding to @mutex.
501 : : *
502 : : * Deprecated: 2.32: Just use a #GMutex
503 : : */
504 : : GMutex *
505 : 118426 : g_static_mutex_get_mutex_impl (GStaticMutex* mutex)
506 : : {
507 : : GMutex *result;
508 : :
509 : : if (!g_thread_supported ())
510 : : return NULL;
511 : :
512 : 118426 : result = g_atomic_pointer_get (&mutex->mutex);
513 : :
514 [ + + ]: 118426 : if (!result)
515 : : {
516 : 1 : G_LOCK (g_static_mutex);
517 : :
518 : 1 : result = mutex->mutex;
519 [ + - ]: 1 : if (!result)
520 : : {
521 : 1 : result = g_mutex_new ();
522 : 1 : g_atomic_pointer_set (&mutex->mutex, result);
523 : : }
524 : :
525 : 1 : G_UNLOCK (g_static_mutex);
526 : : }
527 : :
528 : 118426 : return result;
529 : : }
530 : :
531 : : /* IMPLEMENTATION NOTE:
532 : : *
533 : : * g_static_mutex_lock(), g_static_mutex_trylock() and
534 : : * g_static_mutex_unlock() are all preprocessor macros that wrap the
535 : : * corresponding g_mutex_*() function around a call to
536 : : * g_static_mutex_get_mutex().
537 : : */
538 : :
539 : : /**
540 : : * g_static_mutex_lock: (skip):
541 : : * @mutex: a #GStaticMutex.
542 : : *
543 : : * Works like g_mutex_lock(), but for a #GStaticMutex.
544 : : *
545 : : * Deprecated: 2.32: Use g_mutex_lock()
546 : : */
547 : :
548 : : /**
549 : : * g_static_mutex_trylock: (skip):
550 : : * @mutex: a #GStaticMutex.
551 : : *
552 : : * Works like g_mutex_trylock(), but for a #GStaticMutex.
553 : : *
554 : : * Returns: %TRUE, if the #GStaticMutex could be locked.
555 : : *
556 : : * Deprecated: 2.32: Use g_mutex_trylock()
557 : : */
558 : :
559 : : /**
560 : : * g_static_mutex_unlock: (skip):
561 : : * @mutex: a #GStaticMutex.
562 : : *
563 : : * Works like g_mutex_unlock(), but for a #GStaticMutex.
564 : : *
565 : : * Deprecated: 2.32: Use g_mutex_unlock()
566 : : */
567 : :
568 : : /**
569 : : * g_static_mutex_free: (skip):
570 : : * @mutex: a #GStaticMutex to be freed.
571 : : *
572 : : * Releases all resources allocated to @mutex.
573 : : *
574 : : * You don't have to call this functions for a #GStaticMutex with an
575 : : * unbounded lifetime, i.e. objects declared 'static', but if you have
576 : : * a #GStaticMutex as a member of a structure and the structure is
577 : : * freed, you should also free the #GStaticMutex.
578 : : *
579 : : * Calling g_static_mutex_free() on a locked mutex may result in
580 : : * undefined behaviour.
581 : : *
582 : : * Deprecated: 2.32: Use g_mutex_clear()
583 : : */
584 : : void
585 : 1 : g_static_mutex_free (GStaticMutex* mutex)
586 : : {
587 : : GMutex **runtime_mutex;
588 : :
589 : 1 : g_return_if_fail (mutex);
590 : :
591 : : /* The runtime_mutex is the first (or only) member of GStaticMutex,
592 : : * see both versions (of glibconfig.h) in configure.ac. Note, that
593 : : * this variable is NULL, if g_thread_init() hasn't been called or
594 : : * if we're using the default thread implementation and it provides
595 : : * static mutexes. */
596 : 1 : runtime_mutex = ((GMutex**)mutex);
597 : :
598 [ + - ]: 1 : if (*runtime_mutex)
599 : 1 : g_mutex_free (*runtime_mutex);
600 : :
601 : 1 : *runtime_mutex = NULL;
602 : : }
603 : :
604 : : /* {{{1 GStaticRecMutex */
605 : :
606 : : /**
607 : : * GStaticRecMutex: (skip):
608 : : *
609 : : * A #GStaticRecMutex works like a #GStaticMutex, but it can be locked
610 : : * multiple times by one thread. If you enter it n times, you have to
611 : : * unlock it n times again to let other threads lock it. An exception
612 : : * is the function g_static_rec_mutex_unlock_full(): that allows you to
613 : : * unlock a #GStaticRecMutex completely returning the depth, (i.e. the
614 : : * number of times this mutex was locked). The depth can later be used
615 : : * to restore the state of the #GStaticRecMutex by calling
616 : : * g_static_rec_mutex_lock_full(). In GLib 2.32, #GStaticRecMutex has
617 : : * been deprecated in favor of #GRecMutex.
618 : : *
619 : : * Even though #GStaticRecMutex is not opaque, it should only be used
620 : : * with the following functions.
621 : : *
622 : : * All of the g_static_rec_mutex_* functions can be used even if
623 : : * g_thread_init() has not been called. Then they do nothing, apart
624 : : * from g_static_rec_mutex_trylock(), which does nothing but returning
625 : : * %TRUE.
626 : : */
627 : :
628 : : /**
629 : : * G_STATIC_REC_MUTEX_INIT: (skip):
630 : : *
631 : : * A #GStaticRecMutex must be initialized with this macro before it can
632 : : * be used. This macro can used be to initialize a variable, but it
633 : : * cannot be assigned to a variable. In that case you have to use
634 : : * g_static_rec_mutex_init().
635 : : *
636 : : * |[
637 : : * GStaticRecMutex my_mutex = G_STATIC_REC_MUTEX_INIT;
638 : : * ]|
639 : : */
640 : :
641 : : /**
642 : : * g_static_rec_mutex_init: (skip):
643 : : * @mutex: a #GStaticRecMutex to be initialized.
644 : : *
645 : : * A #GStaticRecMutex must be initialized with this function before it
646 : : * can be used. Alternatively you can initialize it with
647 : : * %G_STATIC_REC_MUTEX_INIT.
648 : : *
649 : : * Deprecated: 2.32: Use g_rec_mutex_init()
650 : : */
651 : : void
652 : 0 : g_static_rec_mutex_init (GStaticRecMutex *mutex)
653 : : {
654 : : static const GStaticRecMutex init_mutex = G_STATIC_REC_MUTEX_INIT;
655 : :
656 : 0 : g_return_if_fail (mutex);
657 : :
658 : 0 : *mutex = init_mutex;
659 : : }
660 : :
661 : : static GRecMutex *
662 : 22 : g_static_rec_mutex_get_rec_mutex_impl (GStaticRecMutex* mutex)
663 : : {
664 : : GRecMutex *result;
665 : :
666 : : if (!g_thread_supported ())
667 : : return NULL;
668 : :
669 : 22 : result = (GRecMutex *) g_atomic_pointer_get (&mutex->mutex.mutex);
670 : :
671 [ + + ]: 22 : if (!result)
672 : : {
673 : 1 : G_LOCK (g_static_mutex);
674 : :
675 : 1 : result = (GRecMutex *) mutex->mutex.mutex;
676 [ + - ]: 1 : if (!result)
677 : : {
678 : 1 : result = g_slice_new (GRecMutex);
679 : 1 : g_rec_mutex_init (result);
680 : 1 : g_atomic_pointer_set (&mutex->mutex.mutex, (GMutex *) result);
681 : : }
682 : :
683 : 1 : G_UNLOCK (g_static_mutex);
684 : : }
685 : :
686 : 22 : return result;
687 : : }
688 : :
689 : : /**
690 : : * g_static_rec_mutex_lock: (skip):
691 : : * @mutex: a #GStaticRecMutex to lock.
692 : : *
693 : : * Locks @mutex. If @mutex is already locked by another thread, the
694 : : * current thread will block until @mutex is unlocked by the other
695 : : * thread. If @mutex is already locked by the calling thread, this
696 : : * functions increases the depth of @mutex and returns immediately.
697 : : *
698 : : * Deprecated: 2.32: Use g_rec_mutex_lock()
699 : : */
700 : : void
701 : 6 : g_static_rec_mutex_lock (GStaticRecMutex* mutex)
702 : : {
703 : : GRecMutex *rm;
704 : 6 : rm = g_static_rec_mutex_get_rec_mutex_impl (mutex);
705 : 6 : g_rec_mutex_lock (rm);
706 : 6 : mutex->depth++;
707 : 6 : }
708 : :
709 : : /**
710 : : * g_static_rec_mutex_trylock: (skip):
711 : : * @mutex: a #GStaticRecMutex to lock.
712 : : *
713 : : * Tries to lock @mutex. If @mutex is already locked by another thread,
714 : : * it immediately returns %FALSE. Otherwise it locks @mutex and returns
715 : : * %TRUE. If @mutex is already locked by the calling thread, this
716 : : * functions increases the depth of @mutex and immediately returns
717 : : * %TRUE.
718 : : *
719 : : * Returns: %TRUE, if @mutex could be locked.
720 : : *
721 : : * Deprecated: 2.32: Use g_rec_mutex_trylock()
722 : : */
723 : : gboolean
724 : 6 : g_static_rec_mutex_trylock (GStaticRecMutex* mutex)
725 : : {
726 : : GRecMutex *rm;
727 : 6 : rm = g_static_rec_mutex_get_rec_mutex_impl (mutex);
728 : :
729 [ + + ]: 6 : if (g_rec_mutex_trylock (rm))
730 : : {
731 : 4 : mutex->depth++;
732 : 4 : return TRUE;
733 : : }
734 : : else
735 : 2 : return FALSE;
736 : : }
737 : :
738 : : /**
739 : : * g_static_rec_mutex_unlock: (skip):
740 : : * @mutex: a #GStaticRecMutex to unlock.
741 : : *
742 : : * Unlocks @mutex. Another thread will be allowed to lock @mutex only
743 : : * when it has been unlocked as many times as it had been locked
744 : : * before. If @mutex is completely unlocked and another thread is
745 : : * blocked in a g_static_rec_mutex_lock() call for @mutex, it will be
746 : : * woken and can lock @mutex itself.
747 : : *
748 : : * Deprecated: 2.32: Use g_rec_mutex_unlock()
749 : : */
750 : : void
751 : 10 : g_static_rec_mutex_unlock (GStaticRecMutex* mutex)
752 : : {
753 : : GRecMutex *rm;
754 : 10 : rm = g_static_rec_mutex_get_rec_mutex_impl (mutex);
755 : 10 : mutex->depth--;
756 : 10 : g_rec_mutex_unlock (rm);
757 : 10 : }
758 : :
759 : : /**
760 : : * g_static_rec_mutex_lock_full: (skip):
761 : : * @mutex: a #GStaticRecMutex to lock.
762 : : * @depth: number of times this mutex has to be unlocked to be
763 : : * completely unlocked.
764 : : *
765 : : * Works like calling g_static_rec_mutex_lock() for @mutex @depth times.
766 : : *
767 : : * Deprecated: 2.32: Use g_rec_mutex_lock()
768 : : */
769 : : void
770 : 0 : g_static_rec_mutex_lock_full (GStaticRecMutex *mutex,
771 : : guint depth)
772 : : {
773 : : GRecMutex *rm;
774 : :
775 : 0 : rm = g_static_rec_mutex_get_rec_mutex_impl (mutex);
776 [ # # ]: 0 : while (depth--)
777 : : {
778 : 0 : g_rec_mutex_lock (rm);
779 : 0 : mutex->depth++;
780 : : }
781 : 0 : }
782 : :
783 : : /**
784 : : * g_static_rec_mutex_unlock_full: (skip):
785 : : * @mutex: a #GStaticRecMutex to completely unlock.
786 : : *
787 : : * Completely unlocks @mutex. If another thread is blocked in a
788 : : * g_static_rec_mutex_lock() call for @mutex, it will be woken and can
789 : : * lock @mutex itself. This function returns the number of times that
790 : : * @mutex has been locked by the current thread. To restore the state
791 : : * before the call to g_static_rec_mutex_unlock_full() you can call
792 : : * g_static_rec_mutex_lock_full() with the depth returned by this
793 : : * function.
794 : : *
795 : : * Returns: number of times @mutex has been locked by the current
796 : : * thread.
797 : : *
798 : : * Deprecated: 2.32: Use g_rec_mutex_unlock()
799 : : */
800 : : guint
801 : 0 : g_static_rec_mutex_unlock_full (GStaticRecMutex *mutex)
802 : : {
803 : : GRecMutex *rm;
804 : : gint depth;
805 : : gint i;
806 : :
807 : 0 : rm = g_static_rec_mutex_get_rec_mutex_impl (mutex);
808 : :
809 : : /* all access to mutex->depth done while still holding the lock */
810 : 0 : depth = mutex->depth;
811 : 0 : i = mutex->depth;
812 : 0 : mutex->depth = 0;
813 : :
814 [ # # ]: 0 : while (i--)
815 : 0 : g_rec_mutex_unlock (rm);
816 : :
817 : 0 : return depth;
818 : : }
819 : :
820 : : /**
821 : : * g_static_rec_mutex_free: (skip):
822 : : * @mutex: a #GStaticRecMutex to be freed.
823 : : *
824 : : * Releases all resources allocated to a #GStaticRecMutex.
825 : : *
826 : : * You don't have to call this functions for a #GStaticRecMutex with an
827 : : * unbounded lifetime, i.e. objects declared 'static', but if you have
828 : : * a #GStaticRecMutex as a member of a structure and the structure is
829 : : * freed, you should also free the #GStaticRecMutex.
830 : : *
831 : : * Deprecated: 2.32: Use g_rec_mutex_clear()
832 : : */
833 : : void
834 : 1 : g_static_rec_mutex_free (GStaticRecMutex *mutex)
835 : : {
836 : 1 : g_return_if_fail (mutex);
837 : :
838 [ + - ]: 1 : if (mutex->mutex.mutex)
839 : : {
840 : 1 : GRecMutex *rm = (GRecMutex *) mutex->mutex.mutex;
841 : :
842 : 1 : g_rec_mutex_clear (rm);
843 : 1 : g_slice_free (GRecMutex, rm);
844 : : }
845 : : }
846 : :
847 : : /* GStaticRWLock {{{1 ----------------------------------------------------- */
848 : :
849 : : /**
850 : : * GStaticRWLock: (skip):
851 : : *
852 : : * The #GStaticRWLock struct represents a read-write lock. A read-write
853 : : * lock can be used for protecting data that some portions of code only
854 : : * read from, while others also write. In such situations it is
855 : : * desirable that several readers can read at once, whereas of course
856 : : * only one writer may write at a time.
857 : : *
858 : : * Take a look at the following example:
859 : : * |[
860 : : * GStaticRWLock rwlock = G_STATIC_RW_LOCK_INIT;
861 : : * GPtrArray *array;
862 : : *
863 : : * gpointer
864 : : * my_array_get (guint index)
865 : : * {
866 : : * gpointer retval = NULL;
867 : : *
868 : : * if (!array)
869 : : * return NULL;
870 : : *
871 : : * g_static_rw_lock_reader_lock (&rwlock);
872 : : * if (index < array->len)
873 : : * retval = g_ptr_array_index (array, index);
874 : : * g_static_rw_lock_reader_unlock (&rwlock);
875 : : *
876 : : * return retval;
877 : : * }
878 : : *
879 : : * void
880 : : * my_array_set (guint index, gpointer data)
881 : : * {
882 : : * g_static_rw_lock_writer_lock (&rwlock);
883 : : *
884 : : * if (!array)
885 : : * array = g_ptr_array_new ();
886 : : *
887 : : * if (index >= array->len)
888 : : * g_ptr_array_set_size (array, index + 1);
889 : : * g_ptr_array_index (array, index) = data;
890 : : *
891 : : * g_static_rw_lock_writer_unlock (&rwlock);
892 : : * }
893 : : * ]|
894 : : *
895 : : * This example shows an array which can be accessed by many readers
896 : : * (the my_array_get() function) simultaneously, whereas the writers
897 : : * (the my_array_set() function) will only be allowed once at a time
898 : : * and only if no readers currently access the array. This is because
899 : : * of the potentially dangerous resizing of the array. Using these
900 : : * functions is fully multi-thread safe now.
901 : : *
902 : : * Most of the time, writers should have precedence over readers. That
903 : : * means, for this implementation, that as soon as a writer wants to
904 : : * lock the data, no other reader is allowed to lock the data, whereas,
905 : : * of course, the readers that already have locked the data are allowed
906 : : * to finish their operation. As soon as the last reader unlocks the
907 : : * data, the writer will lock it.
908 : : *
909 : : * Even though #GStaticRWLock is not opaque, it should only be used
910 : : * with the following functions.
911 : : *
912 : : * All of the g_static_rw_lock_* functions can be used even if
913 : : * g_thread_init() has not been called. Then they do nothing, apart
914 : : * from g_static_rw_lock_*_trylock, which does nothing but returning %TRUE.
915 : : *
916 : : * A read-write lock has a higher overhead than a mutex. For example, both
917 : : * g_static_rw_lock_reader_lock() and g_static_rw_lock_reader_unlock() have
918 : : * to lock and unlock a #GStaticMutex, so it takes at least twice the time
919 : : * to lock and unlock a #GStaticRWLock that it does to lock and unlock a
920 : : * #GStaticMutex. So only data structures that are accessed by multiple
921 : : * readers, and which keep the lock for a considerable time justify a
922 : : * #GStaticRWLock. The above example most probably would fare better with a
923 : : * #GStaticMutex.
924 : : *
925 : : * Deprecated: 2.32: Use a #GRWLock instead
926 : : **/
927 : :
928 : : /**
929 : : * G_STATIC_RW_LOCK_INIT: (skip):
930 : : *
931 : : * A #GStaticRWLock must be initialized with this macro before it can
932 : : * be used. This macro can used be to initialize a variable, but it
933 : : * cannot be assigned to a variable. In that case you have to use
934 : : * g_static_rw_lock_init().
935 : : *
936 : : * |[
937 : : * GStaticRWLock my_lock = G_STATIC_RW_LOCK_INIT;
938 : : * ]|
939 : : */
940 : :
941 : : /**
942 : : * g_static_rw_lock_init: (skip):
943 : : * @lock: a #GStaticRWLock to be initialized.
944 : : *
945 : : * A #GStaticRWLock must be initialized with this function before it
946 : : * can be used. Alternatively you can initialize it with
947 : : * %G_STATIC_RW_LOCK_INIT.
948 : : *
949 : : * Deprecated: 2.32: Use g_rw_lock_init() instead
950 : : */
951 : : void
952 : 0 : g_static_rw_lock_init (GStaticRWLock* lock)
953 : : {
954 : : static const GStaticRWLock init_lock = G_STATIC_RW_LOCK_INIT;
955 : :
956 : 0 : g_return_if_fail (lock);
957 : :
958 : 0 : *lock = init_lock;
959 : : }
960 : :
961 : : inline static void
962 : 17850 : g_static_rw_lock_wait (GCond** cond, GStaticMutex* mutex)
963 : : {
964 [ + + ]: 17850 : if (!*cond)
965 : 2 : *cond = g_cond_new ();
966 : 17850 : g_cond_wait (*cond, g_static_mutex_get_mutex (mutex));
967 : 17850 : }
968 : :
969 : : inline static void
970 : 5764 : g_static_rw_lock_signal (GStaticRWLock* lock)
971 : : {
972 [ + + + - ]: 5764 : if (lock->want_to_write && lock->write_cond)
973 : 4239 : g_cond_signal (lock->write_cond);
974 [ + + + - ]: 1525 : else if (lock->want_to_read && lock->read_cond)
975 : 1524 : g_cond_broadcast (lock->read_cond);
976 : 5764 : }
977 : :
978 : : /**
979 : : * g_static_rw_lock_reader_lock: (skip):
980 : : * @lock: a #GStaticRWLock to lock for reading.
981 : : *
982 : : * Locks @lock for reading. There may be unlimited concurrent locks for
983 : : * reading of a #GStaticRWLock at the same time. If @lock is already
984 : : * locked for writing by another thread or if another thread is already
985 : : * waiting to lock @lock for writing, this function will block until
986 : : * @lock is unlocked by the other writing thread and no other writing
987 : : * threads want to lock @lock. This lock has to be unlocked by
988 : : * g_static_rw_lock_reader_unlock().
989 : : *
990 : : * #GStaticRWLock is not recursive. It might seem to be possible to
991 : : * recursively lock for reading, but that can result in a deadlock, due
992 : : * to writer preference.
993 : : *
994 : : * Deprecated: 2.32: Use g_rw_lock_reader_lock() instead
995 : : */
996 : : void
997 : 17272 : g_static_rw_lock_reader_lock (GStaticRWLock* lock)
998 : : {
999 : 17272 : g_return_if_fail (lock);
1000 : :
1001 [ - + ]: 17272 : if (!g_threads_got_initialized)
1002 : 0 : return;
1003 : :
1004 : 17272 : g_static_mutex_lock (&lock->mutex);
1005 : 17272 : lock->want_to_read++;
1006 [ + + + + ]: 30886 : while (lock->have_writer || lock->want_to_write)
1007 : 13614 : g_static_rw_lock_wait (&lock->read_cond, &lock->mutex);
1008 : 17272 : lock->want_to_read--;
1009 : 17272 : lock->read_counter++;
1010 : 17272 : g_static_mutex_unlock (&lock->mutex);
1011 : : }
1012 : :
1013 : : /**
1014 : : * g_static_rw_lock_reader_trylock: (skip):
1015 : : * @lock: a #GStaticRWLock to lock for reading
1016 : : *
1017 : : * Tries to lock @lock for reading. If @lock is already locked for
1018 : : * writing by another thread or if another thread is already waiting to
1019 : : * lock @lock for writing, immediately returns %FALSE. Otherwise locks
1020 : : * @lock for reading and returns %TRUE. This lock has to be unlocked by
1021 : : * g_static_rw_lock_reader_unlock().
1022 : : *
1023 : : * Returns: %TRUE, if @lock could be locked for reading
1024 : : *
1025 : : * Deprecated: 2.32: Use g_rw_lock_reader_trylock() instead
1026 : : */
1027 : : gboolean
1028 : 4371 : g_static_rw_lock_reader_trylock (GStaticRWLock* lock)
1029 : : {
1030 : 4371 : gboolean ret_val = FALSE;
1031 : :
1032 : 4371 : g_return_val_if_fail (lock, FALSE);
1033 : :
1034 [ - + ]: 4371 : if (!g_threads_got_initialized)
1035 : 0 : return TRUE;
1036 : :
1037 : 4371 : g_static_mutex_lock (&lock->mutex);
1038 [ + + + + ]: 4371 : if (!lock->have_writer && !lock->want_to_write)
1039 : : {
1040 : 1567 : lock->read_counter++;
1041 : 1567 : ret_val = TRUE;
1042 : : }
1043 : 4371 : g_static_mutex_unlock (&lock->mutex);
1044 : 4371 : return ret_val;
1045 : : }
1046 : :
1047 : : /**
1048 : : * g_static_rw_lock_reader_unlock: (skip):
1049 : : * @lock: a #GStaticRWLock to unlock after reading
1050 : : *
1051 : : * Unlocks @lock. If a thread waits to lock @lock for writing and all
1052 : : * locks for reading have been unlocked, the waiting thread is woken up
1053 : : * and can lock @lock for writing.
1054 : : *
1055 : : * Deprecated: 2.32: Use g_rw_lock_reader_unlock() instead
1056 : : */
1057 : : void
1058 : 18839 : g_static_rw_lock_reader_unlock (GStaticRWLock* lock)
1059 : : {
1060 : 18839 : g_return_if_fail (lock);
1061 : :
1062 [ - + ]: 18839 : if (!g_threads_got_initialized)
1063 : 0 : return;
1064 : :
1065 : 18839 : g_static_mutex_lock (&lock->mutex);
1066 : 18839 : lock->read_counter--;
1067 [ + + ]: 18839 : if (lock->read_counter == 0)
1068 : 1272 : g_static_rw_lock_signal (lock);
1069 : 18839 : g_static_mutex_unlock (&lock->mutex);
1070 : : }
1071 : :
1072 : : /**
1073 : : * g_static_rw_lock_writer_lock: (skip):
1074 : : * @lock: a #GStaticRWLock to lock for writing
1075 : : *
1076 : : * Locks @lock for writing. If @lock is already locked for writing or
1077 : : * reading by other threads, this function will block until @lock is
1078 : : * completely unlocked and then lock @lock for writing. While this
1079 : : * functions waits to lock @lock, no other thread can lock @lock for
1080 : : * reading. When @lock is locked for writing, no other thread can lock
1081 : : * @lock (neither for reading nor writing). This lock has to be
1082 : : * unlocked by g_static_rw_lock_writer_unlock().
1083 : : *
1084 : : * Deprecated: 2.32: Use g_rw_lock_writer_lock() instead
1085 : : */
1086 : : void
1087 : 4261 : g_static_rw_lock_writer_lock (GStaticRWLock* lock)
1088 : : {
1089 : 4261 : g_return_if_fail (lock);
1090 : :
1091 [ - + ]: 4261 : if (!g_threads_got_initialized)
1092 : 0 : return;
1093 : :
1094 : 4261 : g_static_mutex_lock (&lock->mutex);
1095 : 4261 : lock->want_to_write++;
1096 [ + + + + ]: 8497 : while (lock->have_writer || lock->read_counter)
1097 : 4236 : g_static_rw_lock_wait (&lock->write_cond, &lock->mutex);
1098 : 4261 : lock->want_to_write--;
1099 : 4261 : lock->have_writer = TRUE;
1100 : 4261 : g_static_mutex_unlock (&lock->mutex);
1101 : : }
1102 : :
1103 : : /**
1104 : : * g_static_rw_lock_writer_trylock: (skip):
1105 : : * @lock: a #GStaticRWLock to lock for writing
1106 : : *
1107 : : * Tries to lock @lock for writing. If @lock is already locked (for
1108 : : * either reading or writing) by another thread, it immediately returns
1109 : : * %FALSE. Otherwise it locks @lock for writing and returns %TRUE. This
1110 : : * lock has to be unlocked by g_static_rw_lock_writer_unlock().
1111 : : *
1112 : : * Returns: %TRUE, if @lock could be locked for writing
1113 : : *
1114 : : * Deprecated: 2.32: Use g_rw_lock_writer_trylock() instead
1115 : : */
1116 : : gboolean
1117 : 1053 : g_static_rw_lock_writer_trylock (GStaticRWLock* lock)
1118 : : {
1119 : 1053 : gboolean ret_val = FALSE;
1120 : :
1121 : 1053 : g_return_val_if_fail (lock, FALSE);
1122 : :
1123 [ - + ]: 1053 : if (!g_threads_got_initialized)
1124 : 0 : return TRUE;
1125 : :
1126 : 1053 : g_static_mutex_lock (&lock->mutex);
1127 [ + + + + ]: 1053 : if (!lock->have_writer && !lock->read_counter)
1128 : : {
1129 : 231 : lock->have_writer = TRUE;
1130 : 231 : ret_val = TRUE;
1131 : : }
1132 : 1053 : g_static_mutex_unlock (&lock->mutex);
1133 : 1053 : return ret_val;
1134 : : }
1135 : :
1136 : : /**
1137 : : * g_static_rw_lock_writer_unlock: (skip):
1138 : : * @lock: a #GStaticRWLock to unlock after writing.
1139 : : *
1140 : : * Unlocks @lock. If a thread is waiting to lock @lock for writing and
1141 : : * all locks for reading have been unlocked, the waiting thread is
1142 : : * woken up and can lock @lock for writing. If no thread is waiting to
1143 : : * lock @lock for writing, and some thread or threads are waiting to
1144 : : * lock @lock for reading, the waiting threads are woken up and can
1145 : : * lock @lock for reading.
1146 : : *
1147 : : * Deprecated: 2.32: Use g_rw_lock_writer_unlock() instead
1148 : : */
1149 : : void
1150 : 4492 : g_static_rw_lock_writer_unlock (GStaticRWLock* lock)
1151 : : {
1152 : 4492 : g_return_if_fail (lock);
1153 : :
1154 [ - + ]: 4492 : if (!g_threads_got_initialized)
1155 : 0 : return;
1156 : :
1157 : 4492 : g_static_mutex_lock (&lock->mutex);
1158 : 4492 : lock->have_writer = FALSE;
1159 : 4492 : g_static_rw_lock_signal (lock);
1160 : 4492 : g_static_mutex_unlock (&lock->mutex);
1161 : : }
1162 : :
1163 : : /**
1164 : : * g_static_rw_lock_free: (skip):
1165 : : * @lock: a #GStaticRWLock to be freed.
1166 : : *
1167 : : * Releases all resources allocated to @lock.
1168 : : *
1169 : : * You don't have to call this functions for a #GStaticRWLock with an
1170 : : * unbounded lifetime, i.e. objects declared 'static', but if you have
1171 : : * a #GStaticRWLock as a member of a structure, and the structure is
1172 : : * freed, you should also free the #GStaticRWLock.
1173 : : *
1174 : : * Deprecated: 2.32: Use a #GRWLock instead
1175 : : */
1176 : : void
1177 : 1 : g_static_rw_lock_free (GStaticRWLock* lock)
1178 : : {
1179 : 1 : g_return_if_fail (lock);
1180 : :
1181 [ + - ]: 1 : if (lock->read_cond)
1182 : : {
1183 : 1 : g_cond_free (lock->read_cond);
1184 : 1 : lock->read_cond = NULL;
1185 : : }
1186 [ + - ]: 1 : if (lock->write_cond)
1187 : : {
1188 : 1 : g_cond_free (lock->write_cond);
1189 : 1 : lock->write_cond = NULL;
1190 : : }
1191 : 1 : g_static_mutex_free (&lock->mutex);
1192 : : }
1193 : :
1194 : : /* GPrivate {{{1 ------------------------------------------------------ */
1195 : :
1196 : : /**
1197 : : * g_private_new: (skip):
1198 : : * @notify: a #GDestroyNotify
1199 : : *
1200 : : * Creates a new #GPrivate.
1201 : : *
1202 : : * Deprecated:2.32: dynamic allocation of #GPrivate is a bad idea. Use
1203 : : * static storage and G_PRIVATE_INIT() instead.
1204 : : *
1205 : : * Returns: a newly allocated #GPrivate (which can never be destroyed)
1206 : : */
1207 : : GPrivate *
1208 : 0 : g_private_new (GDestroyNotify notify)
1209 : : {
1210 : 0 : GPrivate tmp = G_PRIVATE_INIT (notify);
1211 : : GPrivate *key;
1212 : :
1213 : 0 : key = g_slice_new (GPrivate);
1214 : 0 : *key = tmp;
1215 : :
1216 : 0 : return key;
1217 : : }
1218 : :
1219 : : /* {{{1 GStaticPrivate */
1220 : :
1221 : : typedef struct _GStaticPrivateNode GStaticPrivateNode;
1222 : : struct _GStaticPrivateNode
1223 : : {
1224 : : gpointer data;
1225 : : GDestroyNotify destroy;
1226 : : GStaticPrivate *owner;
1227 : : };
1228 : :
1229 : : static void
1230 : 2040 : g_static_private_cleanup (gpointer data)
1231 : : {
1232 : 2040 : GArray *array = data;
1233 : : guint i;
1234 : :
1235 [ + + ]: 4100 : for (i = 0; i < array->len; i++ )
1236 : : {
1237 : 2060 : GStaticPrivateNode *node = &g_array_index (array, GStaticPrivateNode, i);
1238 [ + + ]: 2060 : if (node->destroy)
1239 : 2040 : node->destroy (node->data);
1240 : : }
1241 : :
1242 : 2040 : g_array_free (array, TRUE);
1243 : 2040 : }
1244 : :
1245 : : GPrivate static_private_private = G_PRIVATE_INIT (g_static_private_cleanup);
1246 : :
1247 : : /**
1248 : : * GStaticPrivate: (skip):
1249 : : *
1250 : : * A #GStaticPrivate works almost like a #GPrivate, but it has one
1251 : : * significant advantage. It doesn't need to be created at run-time
1252 : : * like a #GPrivate, but can be defined at compile-time. This is
1253 : : * similar to the difference between #GMutex and #GStaticMutex.
1254 : : *
1255 : : * Now look at our give_me_next_number() example with #GStaticPrivate:
1256 : : * |[
1257 : : * int
1258 : : * give_me_next_number ()
1259 : : * {
1260 : : * static GStaticPrivate current_number_key = G_STATIC_PRIVATE_INIT;
1261 : : * int *current_number = g_static_private_get (¤t_number_key);
1262 : : *
1263 : : * if (!current_number)
1264 : : * {
1265 : : * current_number = g_new (int, 1);
1266 : : * *current_number = 0;
1267 : : * g_static_private_set (¤t_number_key, current_number, g_free);
1268 : : * }
1269 : : *
1270 : : * *current_number = calc_next_number (*current_number);
1271 : : *
1272 : : * return *current_number;
1273 : : * }
1274 : : * ]|
1275 : : */
1276 : :
1277 : : /**
1278 : : * G_STATIC_PRIVATE_INIT: (skip):
1279 : : *
1280 : : * Every #GStaticPrivate must be initialized with this macro, before it
1281 : : * can be used.
1282 : : *
1283 : : * |[
1284 : : * GStaticPrivate my_private = G_STATIC_PRIVATE_INIT;
1285 : : * ]|
1286 : : */
1287 : :
1288 : : /**
1289 : : * g_static_private_init: (skip):
1290 : : * @private_key: a #GStaticPrivate to be initialized
1291 : : *
1292 : : * Initializes @private_key. Alternatively you can initialize it with
1293 : : * %G_STATIC_PRIVATE_INIT.
1294 : : */
1295 : : void
1296 : 2005 : g_static_private_init (GStaticPrivate *private_key)
1297 : : {
1298 : 2005 : private_key->index = 0;
1299 : 2005 : }
1300 : :
1301 : : /**
1302 : : * g_static_private_get: (skip):
1303 : : * @private_key: a #GStaticPrivate
1304 : : *
1305 : : * Works like g_private_get() only for a #GStaticPrivate.
1306 : : *
1307 : : * This function works even if g_thread_init() has not yet been called.
1308 : : *
1309 : : * Returns: the corresponding pointer
1310 : : */
1311 : : gpointer
1312 : 10643 : g_static_private_get (GStaticPrivate *private_key)
1313 : : {
1314 : : GArray *array;
1315 : 10643 : gpointer ret = NULL;
1316 : :
1317 : 10643 : array = g_private_get (&static_private_private);
1318 : :
1319 [ + + + + : 10643 : if (array && private_key->index != 0 && private_key->index <= array->len)
+ + ]
1320 : : {
1321 : : GStaticPrivateNode *node;
1322 : :
1323 : 10575 : node = &g_array_index (array, GStaticPrivateNode, private_key->index - 1);
1324 : :
1325 : : /* Deal with the possibility that the GStaticPrivate which used
1326 : : * to have this index got freed and the index got allocated to
1327 : : * a new one. In this case, the data in the node is stale, so
1328 : : * free it and return NULL.
1329 : : */
1330 [ - + ]: 10575 : if (G_UNLIKELY (node->owner != private_key))
1331 : : {
1332 [ # # ]: 0 : if (node->destroy)
1333 : 0 : node->destroy (node->data);
1334 : 0 : node->destroy = NULL;
1335 : 0 : node->data = NULL;
1336 : 0 : node->owner = NULL;
1337 : : }
1338 : 10575 : ret = node->data;
1339 : : }
1340 : :
1341 : 10643 : return ret;
1342 : : }
1343 : :
1344 : : /**
1345 : : * g_static_private_set: (skip):
1346 : : * @private_key: a #GStaticPrivate
1347 : : * @data: the new pointer
1348 : : * @notify: a function to be called with the pointer whenever the
1349 : : * current thread ends or sets this pointer again
1350 : : *
1351 : : * Sets the pointer keyed to @private_key for the current thread and
1352 : : * the function @notify to be called with that pointer (%NULL or
1353 : : * non-%NULL), whenever the pointer is set again or whenever the
1354 : : * current thread ends.
1355 : : *
1356 : : * This function works even if g_thread_init() has not yet been called.
1357 : : * If g_thread_init() is called later, the @data keyed to @private_key
1358 : : * will be inherited only by the main thread, i.e. the one that called
1359 : : * g_thread_init().
1360 : : *
1361 : : * @notify is used quite differently from @destructor in g_private_new().
1362 : : */
1363 : : void
1364 : 12330 : g_static_private_set (GStaticPrivate *private_key,
1365 : : gpointer data,
1366 : : GDestroyNotify notify)
1367 : : {
1368 : : GArray *array;
1369 : : static guint next_index = 0;
1370 : : GStaticPrivateNode *node;
1371 : :
1372 [ + + ]: 12330 : if (!private_key->index)
1373 : : {
1374 : 2010 : G_LOCK (g_thread);
1375 : :
1376 [ + - ]: 2010 : if (!private_key->index)
1377 : : {
1378 [ + + ]: 2010 : if (g_thread_free_indices)
1379 : : {
1380 : 2005 : private_key->index = GPOINTER_TO_UINT (g_thread_free_indices->data);
1381 : 2005 : g_thread_free_indices = g_slist_delete_link (g_thread_free_indices,
1382 : : g_thread_free_indices);
1383 : : }
1384 : : else
1385 : 5 : private_key->index = ++next_index;
1386 : : }
1387 : :
1388 : 2010 : G_UNLOCK (g_thread);
1389 : : }
1390 : :
1391 : 12330 : array = g_private_get (&static_private_private);
1392 [ + + ]: 12330 : if (!array)
1393 : : {
1394 : 2041 : array = g_array_new (FALSE, TRUE, sizeof (GStaticPrivateNode));
1395 : 2041 : g_private_set (&static_private_private, array);
1396 : : }
1397 [ + + ]: 12330 : if (private_key->index > array->len)
1398 : 2061 : g_array_set_size (array, private_key->index);
1399 : :
1400 : 12330 : node = &g_array_index (array, GStaticPrivateNode, private_key->index - 1);
1401 : :
1402 [ + + ]: 12330 : if (node->destroy)
1403 : 276 : node->destroy (node->data);
1404 : :
1405 : 12330 : node->data = data;
1406 : 12330 : node->destroy = notify;
1407 : 12330 : node->owner = private_key;
1408 : 12330 : }
1409 : :
1410 : : /**
1411 : : * g_static_private_free: (skip):
1412 : : * @private_key: a #GStaticPrivate to be freed
1413 : : *
1414 : : * Releases all resources allocated to @private_key.
1415 : : *
1416 : : * You don't have to call this functions for a #GStaticPrivate with an
1417 : : * unbounded lifetime, i.e. objects declared 'static', but if you have
1418 : : * a #GStaticPrivate as a member of a structure and the structure is
1419 : : * freed, you should also free the #GStaticPrivate.
1420 : : */
1421 : : void
1422 : 2009 : g_static_private_free (GStaticPrivate *private_key)
1423 : : {
1424 : 2009 : guint idx = private_key->index;
1425 : :
1426 [ - + ]: 2009 : if (!idx)
1427 : 0 : return;
1428 : :
1429 : 2009 : private_key->index = 0;
1430 : :
1431 : : /* Freeing the per-thread data is deferred to either the
1432 : : * thread end or the next g_static_private_get() call for
1433 : : * the same index.
1434 : : */
1435 : 2009 : G_LOCK (g_thread);
1436 : 4018 : g_thread_free_indices = g_slist_prepend (g_thread_free_indices,
1437 : 2009 : GUINT_TO_POINTER (idx));
1438 : 2009 : G_UNLOCK (g_thread);
1439 : : }
1440 : :
1441 : : /* GMutex {{{1 ------------------------------------------------------ */
1442 : :
1443 : : /**
1444 : : * g_mutex_new: (skip):
1445 : : *
1446 : : * Allocates and initializes a new #GMutex.
1447 : : *
1448 : : * Returns: a newly allocated #GMutex. Use g_mutex_free() to free
1449 : : *
1450 : : * Deprecated: 2.32: GMutex can now be statically allocated, or embedded
1451 : : * in structures and initialised with g_mutex_init().
1452 : : */
1453 : : GMutex *
1454 : 4 : g_mutex_new (void)
1455 : : {
1456 : : GMutex *mutex;
1457 : :
1458 : 4 : mutex = g_slice_new (GMutex);
1459 : 4 : g_mutex_init (mutex);
1460 : :
1461 : 4 : return mutex;
1462 : : }
1463 : :
1464 : : /**
1465 : : * g_mutex_free: (skip):
1466 : : * @mutex: a #GMutex
1467 : : *
1468 : : * Destroys a @mutex that has been created with g_mutex_new().
1469 : : *
1470 : : * Calling g_mutex_free() on a locked mutex may result
1471 : : * in undefined behaviour.
1472 : : *
1473 : : * Deprecated: 2.32: GMutex can now be statically allocated, or embedded
1474 : : * in structures and initialised with g_mutex_init().
1475 : : */
1476 : : void
1477 : 4 : g_mutex_free (GMutex *mutex)
1478 : : {
1479 : 4 : g_mutex_clear (mutex);
1480 : 4 : g_slice_free (GMutex, mutex);
1481 : 4 : }
1482 : :
1483 : : /* GCond {{{1 ------------------------------------------------------ */
1484 : :
1485 : : /**
1486 : : * g_cond_new: (skip):
1487 : : *
1488 : : * Allocates and initializes a new #GCond.
1489 : : *
1490 : : * Returns: a newly allocated #GCond. Free with g_cond_free()
1491 : : *
1492 : : * Deprecated: 2.32: GCond can now be statically allocated, or embedded
1493 : : * in structures and initialised with g_cond_init().
1494 : : */
1495 : : GCond *
1496 : 4 : g_cond_new (void)
1497 : : {
1498 : : GCond *cond;
1499 : :
1500 : 4 : cond = g_slice_new (GCond);
1501 : 4 : g_cond_init (cond);
1502 : :
1503 : 4 : return cond;
1504 : : }
1505 : :
1506 : : /**
1507 : : * g_cond_free: (skip):
1508 : : * @cond: a #GCond
1509 : : *
1510 : : * Destroys a #GCond that has been created with g_cond_new().
1511 : : *
1512 : : * Calling g_cond_free() for a #GCond on which threads are
1513 : : * blocking leads to undefined behaviour.
1514 : : *
1515 : : * Deprecated: 2.32: GCond can now be statically allocated, or embedded
1516 : : * in structures and initialised with g_cond_init().
1517 : : */
1518 : : void
1519 : 4 : g_cond_free (GCond *cond)
1520 : : {
1521 : 4 : g_cond_clear (cond);
1522 : 4 : g_slice_free (GCond, cond);
1523 : 4 : }
1524 : :
1525 : : /**
1526 : : * g_cond_timed_wait: (skip):
1527 : : * @cond: a #GCond
1528 : : * @mutex: a #GMutex that is currently locked
1529 : : * @abs_time: a #GTimeVal, determining the final time
1530 : : *
1531 : : * Waits until this thread is woken up on @cond, but not longer than
1532 : : * until the time specified by @abs_time. The @mutex is unlocked before
1533 : : * falling asleep and locked again before resuming.
1534 : : *
1535 : : * If @abs_time is %NULL, g_cond_timed_wait() acts like g_cond_wait().
1536 : : *
1537 : : * This function can be used even if g_thread_init() has not yet been
1538 : : * called, and, in that case, will immediately return %TRUE.
1539 : : *
1540 : : * To easily calculate @abs_time a combination of g_get_real_time()
1541 : : * and g_time_val_add() can be used.
1542 : : *
1543 : : * Returns: %TRUE if @cond was signalled, or %FALSE on timeout
1544 : : *
1545 : : * Deprecated:2.32: Use g_cond_wait_until() instead.
1546 : : */
1547 : : gboolean
1548 : 0 : g_cond_timed_wait (GCond *cond,
1549 : : GMutex *mutex,
1550 : : GTimeVal *abs_time)
1551 : : {
1552 : : gint64 end_time;
1553 : :
1554 [ # # ]: 0 : if (abs_time == NULL)
1555 : : {
1556 : 0 : g_cond_wait (cond, mutex);
1557 : 0 : return TRUE;
1558 : : }
1559 : :
1560 : 0 : end_time = abs_time->tv_sec;
1561 : 0 : end_time *= 1000000;
1562 : 0 : end_time += abs_time->tv_usec;
1563 : :
1564 : : /* would be nice if we had clock_rtoffset, but that didn't seem to
1565 : : * make it into the kernel yet...
1566 : : */
1567 : 0 : end_time += g_get_monotonic_time () - g_get_real_time ();
1568 : :
1569 : 0 : return g_cond_wait_until (cond, mutex, end_time);
1570 : : }
1571 : :
1572 : : /* {{{1 Epilogue */
1573 : : /* vim: set foldmethod=marker: */
|