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