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