| 1 | /* GLIB - Library of useful routines for C programming | 
| 2 |  * Copyright (C) 1995-1997  Peter Mattis, Spencer Kimball and Josh MacDonald | 
| 3 |  * | 
| 4 |  * This library is free software; you can redistribute it and/or | 
| 5 |  * modify it under the terms of the GNU Lesser General Public | 
| 6 |  * License as published by the Free Software Foundation; either | 
| 7 |  * version 2.1 of the License, or (at your option) any later version. | 
| 8 |  * | 
| 9 |  * This library is distributed in the hope that it will be useful, but | 
| 10 |  * WITHOUT ANY WARRANTY; without even the implied warranty of | 
| 11 |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | 
| 12 |  * Lesser General Public License for more details. | 
| 13 |  * | 
| 14 |  * You should have received a copy of the GNU Lesser General Public | 
| 15 |  * License along with this library; if not, see <http://www.gnu.org/licenses/>. | 
| 16 |  */ | 
| 17 |  | 
| 18 | /* | 
| 19 |  * Modified by the GLib Team and others 1997-2000.  See the AUTHORS | 
| 20 |  * file for a list of people on the GLib Team.  See the ChangeLog | 
| 21 |  * files for a list of changes.  These files are distributed with | 
| 22 |  * GLib at ftp://ftp.gtk.org/pub/gtk/. | 
| 23 |  */ | 
| 24 |  | 
| 25 | #ifndef __G_THREAD_H__ | 
| 26 | #define __G_THREAD_H__ | 
| 27 |  | 
| 28 | #if !defined (__GLIB_H_INSIDE__) && !defined (GLIB_COMPILATION) | 
| 29 | #error "Only <glib.h> can be included directly." | 
| 30 | #endif | 
| 31 |  | 
| 32 | #include <glib/gatomic.h> | 
| 33 | #include <glib/gerror.h> | 
| 34 | #include <glib/gutils.h> | 
| 35 |  | 
| 36 | G_BEGIN_DECLS | 
| 37 |  | 
| 38 | #define G_THREAD_ERROR g_thread_error_quark () | 
| 39 | GLIB_AVAILABLE_IN_ALL | 
| 40 | GQuark g_thread_error_quark (void); | 
| 41 |  | 
| 42 | typedef enum | 
| 43 | { | 
| 44 |   G_THREAD_ERROR_AGAIN /* Resource temporarily unavailable */ | 
| 45 | } GThreadError; | 
| 46 |  | 
| 47 | typedef gpointer (*GThreadFunc) (gpointer data); | 
| 48 |  | 
| 49 | typedef struct _GThread         GThread; | 
| 50 |  | 
| 51 | typedef union  _GMutex          GMutex; | 
| 52 | typedef struct _GRecMutex       GRecMutex; | 
| 53 | typedef struct _GRWLock         GRWLock; | 
| 54 | typedef struct _GCond           GCond; | 
| 55 | typedef struct _GPrivate        GPrivate; | 
| 56 | typedef struct _GOnce           GOnce; | 
| 57 |  | 
| 58 | union _GMutex | 
| 59 | { | 
| 60 |   /*< private >*/ | 
| 61 |   gpointer p; | 
| 62 |   guint i[2]; | 
| 63 | }; | 
| 64 |  | 
| 65 | struct _GRWLock | 
| 66 | { | 
| 67 |   /*< private >*/ | 
| 68 |   gpointer p; | 
| 69 |   guint i[2]; | 
| 70 | }; | 
| 71 |  | 
| 72 | struct _GCond | 
| 73 | { | 
| 74 |   /*< private >*/ | 
| 75 |   gpointer p; | 
| 76 |   guint i[2]; | 
| 77 | }; | 
| 78 |  | 
| 79 | struct _GRecMutex | 
| 80 | { | 
| 81 |   /*< private >*/ | 
| 82 |   gpointer p; | 
| 83 |   guint i[2]; | 
| 84 | }; | 
| 85 |  | 
| 86 | #define G_PRIVATE_INIT(notify) { NULL, (notify), { NULL, NULL } } | 
| 87 | struct _GPrivate | 
| 88 | { | 
| 89 |   /*< private >*/ | 
| 90 |   gpointer       p; | 
| 91 |   GDestroyNotify notify; | 
| 92 |   gpointer future[2]; | 
| 93 | }; | 
| 94 |  | 
| 95 | typedef enum | 
| 96 | { | 
| 97 |   G_ONCE_STATUS_NOTCALLED, | 
| 98 |   G_ONCE_STATUS_PROGRESS, | 
| 99 |   G_ONCE_STATUS_READY | 
| 100 | } GOnceStatus; | 
| 101 |  | 
| 102 | #define G_ONCE_INIT { G_ONCE_STATUS_NOTCALLED, NULL } | 
| 103 | struct _GOnce | 
| 104 | { | 
| 105 |   volatile GOnceStatus status; | 
| 106 |   volatile gpointer retval; | 
| 107 | }; | 
| 108 |  | 
| 109 | #define G_LOCK_NAME(name)             g__ ## name ## _lock | 
| 110 | #define G_LOCK_DEFINE_STATIC(name)    static G_LOCK_DEFINE (name) | 
| 111 | #define G_LOCK_DEFINE(name)           GMutex G_LOCK_NAME (name) | 
| 112 | #define G_LOCK_EXTERN(name)           extern GMutex G_LOCK_NAME (name) | 
| 113 |  | 
| 114 | #ifdef G_DEBUG_LOCKS | 
| 115 | #  define G_LOCK(name)                G_STMT_START{             \ | 
| 116 |       g_log (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG,                   \ | 
| 117 |              "file %s: line %d (%s): locking: %s ",             \ | 
| 118 |              __FILE__,        __LINE__, G_STRFUNC,              \ | 
| 119 |              #name);                                            \ | 
| 120 |       g_mutex_lock (&G_LOCK_NAME (name));                       \ | 
| 121 |    }G_STMT_END | 
| 122 | #  define G_UNLOCK(name)              G_STMT_START{             \ | 
| 123 |       g_log (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG,                   \ | 
| 124 |              "file %s: line %d (%s): unlocking: %s ",           \ | 
| 125 |              __FILE__,        __LINE__, G_STRFUNC,              \ | 
| 126 |              #name);                                            \ | 
| 127 |      g_mutex_unlock (&G_LOCK_NAME (name));                      \ | 
| 128 |    }G_STMT_END | 
| 129 | #  define G_TRYLOCK(name)                                       \ | 
| 130 |       (g_log (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG,                  \ | 
| 131 |              "file %s: line %d (%s): try locking: %s ",         \ | 
| 132 |              __FILE__,        __LINE__, G_STRFUNC,              \ | 
| 133 |              #name), g_mutex_trylock (&G_LOCK_NAME (name))) | 
| 134 | #else  /* !G_DEBUG_LOCKS */ | 
| 135 | #  define G_LOCK(name) g_mutex_lock       (&G_LOCK_NAME (name)) | 
| 136 | #  define G_UNLOCK(name) g_mutex_unlock   (&G_LOCK_NAME (name)) | 
| 137 | #  define G_TRYLOCK(name) g_mutex_trylock (&G_LOCK_NAME (name)) | 
| 138 | #endif /* !G_DEBUG_LOCKS */ | 
| 139 |  | 
| 140 | GLIB_AVAILABLE_IN_2_32 | 
| 141 | GThread *       g_thread_ref                    (GThread        *thread); | 
| 142 | GLIB_AVAILABLE_IN_2_32 | 
| 143 | void            g_thread_unref                  (GThread        *thread); | 
| 144 | GLIB_AVAILABLE_IN_2_32 | 
| 145 | GThread *       g_thread_new                    (const gchar    *name, | 
| 146 |                                                  GThreadFunc     func, | 
| 147 |                                                  gpointer        data); | 
| 148 | GLIB_AVAILABLE_IN_2_32 | 
| 149 | GThread *       g_thread_try_new                (const gchar    *name, | 
| 150 |                                                  GThreadFunc     func, | 
| 151 |                                                  gpointer        data, | 
| 152 |                                                  GError        **error); | 
| 153 | GLIB_AVAILABLE_IN_ALL | 
| 154 | GThread *       g_thread_self                   (void); | 
| 155 | GLIB_AVAILABLE_IN_ALL | 
| 156 | void            g_thread_exit                   (gpointer        retval); | 
| 157 | GLIB_AVAILABLE_IN_ALL | 
| 158 | gpointer        g_thread_join                   (GThread        *thread); | 
| 159 | GLIB_AVAILABLE_IN_ALL | 
| 160 | void            g_thread_yield                  (void); | 
| 161 |  | 
| 162 |  | 
| 163 | GLIB_AVAILABLE_IN_2_32 | 
| 164 | void            g_mutex_init                    (GMutex         *mutex); | 
| 165 | GLIB_AVAILABLE_IN_2_32 | 
| 166 | void            g_mutex_clear                   (GMutex         *mutex); | 
| 167 | GLIB_AVAILABLE_IN_ALL | 
| 168 | void            g_mutex_lock                    (GMutex         *mutex); | 
| 169 | GLIB_AVAILABLE_IN_ALL | 
| 170 | gboolean        g_mutex_trylock                 (GMutex         *mutex); | 
| 171 | GLIB_AVAILABLE_IN_ALL | 
| 172 | void            g_mutex_unlock                  (GMutex         *mutex); | 
| 173 |  | 
| 174 | GLIB_AVAILABLE_IN_2_32 | 
| 175 | void            g_rw_lock_init                  (GRWLock        *rw_lock); | 
| 176 | GLIB_AVAILABLE_IN_2_32 | 
| 177 | void            g_rw_lock_clear                 (GRWLock        *rw_lock); | 
| 178 | GLIB_AVAILABLE_IN_2_32 | 
| 179 | void            g_rw_lock_writer_lock           (GRWLock        *rw_lock); | 
| 180 | GLIB_AVAILABLE_IN_2_32 | 
| 181 | gboolean        g_rw_lock_writer_trylock        (GRWLock        *rw_lock); | 
| 182 | GLIB_AVAILABLE_IN_2_32 | 
| 183 | void            g_rw_lock_writer_unlock         (GRWLock        *rw_lock); | 
| 184 | GLIB_AVAILABLE_IN_2_32 | 
| 185 | void            g_rw_lock_reader_lock           (GRWLock        *rw_lock); | 
| 186 | GLIB_AVAILABLE_IN_2_32 | 
| 187 | gboolean        g_rw_lock_reader_trylock        (GRWLock        *rw_lock); | 
| 188 | GLIB_AVAILABLE_IN_2_32 | 
| 189 | void            g_rw_lock_reader_unlock         (GRWLock        *rw_lock); | 
| 190 |  | 
| 191 | GLIB_AVAILABLE_IN_2_32 | 
| 192 | void            g_rec_mutex_init                (GRecMutex      *rec_mutex); | 
| 193 | GLIB_AVAILABLE_IN_2_32 | 
| 194 | void            g_rec_mutex_clear               (GRecMutex      *rec_mutex); | 
| 195 | GLIB_AVAILABLE_IN_2_32 | 
| 196 | void            g_rec_mutex_lock                (GRecMutex      *rec_mutex); | 
| 197 | GLIB_AVAILABLE_IN_2_32 | 
| 198 | gboolean        g_rec_mutex_trylock             (GRecMutex      *rec_mutex); | 
| 199 | GLIB_AVAILABLE_IN_2_32 | 
| 200 | void            g_rec_mutex_unlock              (GRecMutex      *rec_mutex); | 
| 201 |  | 
| 202 | GLIB_AVAILABLE_IN_2_32 | 
| 203 | void            g_cond_init                     (GCond          *cond); | 
| 204 | GLIB_AVAILABLE_IN_2_32 | 
| 205 | void            g_cond_clear                    (GCond          *cond); | 
| 206 | GLIB_AVAILABLE_IN_ALL | 
| 207 | void            g_cond_wait                     (GCond          *cond, | 
| 208 |                                                  GMutex         *mutex); | 
| 209 | GLIB_AVAILABLE_IN_ALL | 
| 210 | void            g_cond_signal                   (GCond          *cond); | 
| 211 | GLIB_AVAILABLE_IN_ALL | 
| 212 | void            g_cond_broadcast                (GCond          *cond); | 
| 213 | GLIB_AVAILABLE_IN_2_32 | 
| 214 | gboolean        g_cond_wait_until               (GCond          *cond, | 
| 215 |                                                  GMutex         *mutex, | 
| 216 |                                                  gint64          end_time); | 
| 217 |  | 
| 218 | GLIB_AVAILABLE_IN_ALL | 
| 219 | gpointer        g_private_get                   (GPrivate       *key); | 
| 220 | GLIB_AVAILABLE_IN_ALL | 
| 221 | void            g_private_set                   (GPrivate       *key, | 
| 222 |                                                  gpointer        value); | 
| 223 | GLIB_AVAILABLE_IN_2_32 | 
| 224 | void            g_private_replace               (GPrivate       *key, | 
| 225 |                                                  gpointer        value); | 
| 226 |  | 
| 227 | GLIB_AVAILABLE_IN_ALL | 
| 228 | gpointer        g_once_impl                     (GOnce          *once, | 
| 229 |                                                  GThreadFunc     func, | 
| 230 |                                                  gpointer        arg); | 
| 231 | GLIB_AVAILABLE_IN_ALL | 
| 232 | gboolean        g_once_init_enter               (volatile void  *location); | 
| 233 | GLIB_AVAILABLE_IN_ALL | 
| 234 | void            g_once_init_leave               (volatile void  *location, | 
| 235 |                                                  gsize           result); | 
| 236 |  | 
| 237 | /* Use C11-style atomic extensions to check the fast path for status=ready. If | 
| 238 |  * they are not available, fall back to using a mutex and condition variable in | 
| 239 |  * g_once_impl(). | 
| 240 |  * | 
| 241 |  * On the C11-style codepath, only the load of once->status needs to be atomic, | 
| 242 |  * as the writes to it and once->retval in g_once_impl() are related by a | 
| 243 |  * happens-before relation. Release-acquire semantics are defined such that any | 
| 244 |  * atomic/non-atomic write which happens-before a store/release is guaranteed to | 
| 245 |  * be seen by the load/acquire of the same atomic variable. */ | 
| 246 | #if defined(G_ATOMIC_LOCK_FREE) && defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4) && defined(__ATOMIC_SEQ_CST) | 
| 247 | # define g_once(once, func, arg) \ | 
| 248 |   ((__atomic_load_n (&(once)->status, __ATOMIC_ACQUIRE) == G_ONCE_STATUS_READY) ? \ | 
| 249 |    (once)->retval : \ | 
| 250 |    g_once_impl ((once), (func), (arg))) | 
| 251 | #else | 
| 252 | # define g_once(once, func, arg) g_once_impl ((once), (func), (arg)) | 
| 253 | #endif | 
| 254 |  | 
| 255 | #ifdef __GNUC__ | 
| 256 | # define g_once_init_enter(location) \ | 
| 257 |   (G_GNUC_EXTENSION ({                                               \ | 
| 258 |     G_STATIC_ASSERT (sizeof *(location) == sizeof (gpointer));       \ | 
| 259 |     (void) (0 ? (gpointer) *(location) : NULL);                      \ | 
| 260 |     (!g_atomic_pointer_get (location) &&                             \ | 
| 261 |      g_once_init_enter (location));                                  \ | 
| 262 |   })) | 
| 263 | # define g_once_init_leave(location, result) \ | 
| 264 |   (G_GNUC_EXTENSION ({                                               \ | 
| 265 |     G_STATIC_ASSERT (sizeof *(location) == sizeof (gpointer));       \ | 
| 266 |     0 ? (void) (*(location) = (result)) : (void) 0;                  \ | 
| 267 |     g_once_init_leave ((location), (gsize) (result));                \ | 
| 268 |   })) | 
| 269 | #else | 
| 270 | # define g_once_init_enter(location) \ | 
| 271 |   (g_once_init_enter((location))) | 
| 272 | # define g_once_init_leave(location, result) \ | 
| 273 |   (g_once_init_leave((location), (gsize) (result))) | 
| 274 | #endif | 
| 275 |  | 
| 276 | GLIB_AVAILABLE_IN_2_36 | 
| 277 | guint          g_get_num_processors (void); | 
| 278 |  | 
| 279 | /** | 
| 280 |  * GMutexLocker: | 
| 281 |  * | 
| 282 |  * Opaque type. See g_mutex_locker_new() for details. | 
| 283 |  * Since: 2.44 | 
| 284 |  */ | 
| 285 | typedef void GMutexLocker; | 
| 286 |  | 
| 287 | /** | 
| 288 |  * g_mutex_locker_new: | 
| 289 |  * @mutex: a mutex to lock | 
| 290 |  * | 
| 291 |  * Lock @mutex and return a new #GMutexLocker. Unlock with | 
| 292 |  * g_mutex_locker_free(). Using g_mutex_unlock() on @mutex | 
| 293 |  * while a #GMutexLocker exists can lead to undefined behaviour. | 
| 294 |  * | 
| 295 |  * No allocation is performed, it is equivalent to a g_mutex_lock() call. | 
| 296 |  * | 
| 297 |  * This is intended to be used with g_autoptr().  Note that g_autoptr() | 
| 298 |  * is only available when using GCC or clang, so the following example | 
| 299 |  * will only work with those compilers: | 
| 300 |  * |[ | 
| 301 |  * typedef struct | 
| 302 |  * { | 
| 303 |  *   ... | 
| 304 |  *   GMutex mutex; | 
| 305 |  *   ... | 
| 306 |  * } MyObject; | 
| 307 |  * | 
| 308 |  * static void | 
| 309 |  * my_object_do_stuff (MyObject *self) | 
| 310 |  * { | 
| 311 |  *   g_autoptr(GMutexLocker) locker = g_mutex_locker_new (&self->mutex); | 
| 312 |  * | 
| 313 |  *   // Code with mutex locked here | 
| 314 |  * | 
| 315 |  *   if (cond) | 
| 316 |  *     // No need to unlock | 
| 317 |  *     return; | 
| 318 |  * | 
| 319 |  *   // Optionally early unlock | 
| 320 |  *   g_clear_pointer (&locker, g_mutex_locker_free); | 
| 321 |  * | 
| 322 |  *   // Code with mutex unlocked here | 
| 323 |  * } | 
| 324 |  * ]| | 
| 325 |  * | 
| 326 |  * Returns: a #GMutexLocker | 
| 327 |  * Since: 2.44 | 
| 328 |  */ | 
| 329 | GLIB_AVAILABLE_STATIC_INLINE_IN_2_44 | 
| 330 | static inline GMutexLocker * | 
| 331 | g_mutex_locker_new (GMutex *mutex) | 
| 332 | { | 
| 333 |   g_mutex_lock (mutex); | 
| 334 |   return (GMutexLocker *) mutex; | 
| 335 | } | 
| 336 |  | 
| 337 | /** | 
| 338 |  * g_mutex_locker_free: | 
| 339 |  * @locker: a GMutexLocker | 
| 340 |  * | 
| 341 |  * Unlock @locker's mutex. See g_mutex_locker_new() for details. | 
| 342 |  * | 
| 343 |  * No memory is freed, it is equivalent to a g_mutex_unlock() call. | 
| 344 |  * | 
| 345 |  * Since: 2.44 | 
| 346 |  */ | 
| 347 | GLIB_AVAILABLE_STATIC_INLINE_IN_2_44 | 
| 348 | static inline void | 
| 349 | g_mutex_locker_free (GMutexLocker *locker) | 
| 350 | { | 
| 351 |   g_mutex_unlock ((GMutex *) locker); | 
| 352 | } | 
| 353 |  | 
| 354 | /** | 
| 355 |  * GRecMutexLocker: | 
| 356 |  * | 
| 357 |  * Opaque type. See g_rec_mutex_locker_new() for details. | 
| 358 |  * Since: 2.60 | 
| 359 |  */ | 
| 360 | typedef void GRecMutexLocker; | 
| 361 |  | 
| 362 | /** | 
| 363 |  * g_rec_mutex_locker_new: | 
| 364 |  * @rec_mutex: a recursive mutex to lock | 
| 365 |  * | 
| 366 |  * Lock @rec_mutex and return a new #GRecMutexLocker. Unlock with | 
| 367 |  * g_rec_mutex_locker_free(). Using g_rec_mutex_unlock() on @rec_mutex | 
| 368 |  * while a #GRecMutexLocker exists can lead to undefined behaviour. | 
| 369 |  * | 
| 370 |  * No allocation is performed, it is equivalent to a g_rec_mutex_lock() call. | 
| 371 |  * | 
| 372 |  * This is intended to be used with g_autoptr().  Note that g_autoptr() | 
| 373 |  * is only available when using GCC or clang, so the following example | 
| 374 |  * will only work with those compilers: | 
| 375 |  * |[ | 
| 376 |  * typedef struct | 
| 377 |  * { | 
| 378 |  *   ... | 
| 379 |  *   GRecMutex rec_mutex; | 
| 380 |  *   ... | 
| 381 |  * } MyObject; | 
| 382 |  * | 
| 383 |  * static void | 
| 384 |  * my_object_do_stuff (MyObject *self) | 
| 385 |  * { | 
| 386 |  *   g_autoptr(GRecMutexLocker) locker = g_rec_mutex_locker_new (&self->rec_mutex); | 
| 387 |  * | 
| 388 |  *   // Code with rec_mutex locked here | 
| 389 |  * | 
| 390 |  *   if (cond) | 
| 391 |  *     // No need to unlock | 
| 392 |  *     return; | 
| 393 |  * | 
| 394 |  *   // Optionally early unlock | 
| 395 |  *   g_clear_pointer (&locker, g_rec_mutex_locker_free); | 
| 396 |  * | 
| 397 |  *   // Code with rec_mutex unlocked here | 
| 398 |  * } | 
| 399 |  * ]| | 
| 400 |  * | 
| 401 |  * Returns: a #GRecMutexLocker | 
| 402 |  * Since: 2.60 | 
| 403 |  */ | 
| 404 | G_GNUC_BEGIN_IGNORE_DEPRECATIONS | 
| 405 | GLIB_AVAILABLE_STATIC_INLINE_IN_2_60 | 
| 406 | static inline GRecMutexLocker * | 
| 407 | g_rec_mutex_locker_new (GRecMutex *rec_mutex) | 
| 408 | { | 
| 409 |   g_rec_mutex_lock (rec_mutex); | 
| 410 |   return (GRecMutexLocker *) rec_mutex; | 
| 411 | } | 
| 412 | G_GNUC_END_IGNORE_DEPRECATIONS | 
| 413 |  | 
| 414 | /** | 
| 415 |  * g_rec_mutex_locker_free: | 
| 416 |  * @locker: a GRecMutexLocker | 
| 417 |  * | 
| 418 |  * Unlock @locker's recursive mutex. See g_rec_mutex_locker_new() for details. | 
| 419 |  * | 
| 420 |  * No memory is freed, it is equivalent to a g_rec_mutex_unlock() call. | 
| 421 |  * | 
| 422 |  * Since: 2.60 | 
| 423 |  */ | 
| 424 | G_GNUC_BEGIN_IGNORE_DEPRECATIONS | 
| 425 | GLIB_AVAILABLE_STATIC_INLINE_IN_2_60 | 
| 426 | static inline void | 
| 427 | g_rec_mutex_locker_free (GRecMutexLocker *locker) | 
| 428 | { | 
| 429 |   g_rec_mutex_unlock ((GRecMutex *) locker); | 
| 430 | } | 
| 431 | G_GNUC_END_IGNORE_DEPRECATIONS | 
| 432 |  | 
| 433 | /** | 
| 434 |  * GRWLockWriterLocker: | 
| 435 |  * | 
| 436 |  * Opaque type. See g_rw_lock_writer_locker_new() for details. | 
| 437 |  * Since: 2.62 | 
| 438 |  */ | 
| 439 | typedef void GRWLockWriterLocker; | 
| 440 |  | 
| 441 | /** | 
| 442 |  * g_rw_lock_writer_locker_new: | 
| 443 |  * @rw_lock: a #GRWLock | 
| 444 |  * | 
| 445 |  * Obtain a write lock on @rw_lock and return a new #GRWLockWriterLocker. | 
| 446 |  * Unlock with g_rw_lock_writer_locker_free(). Using g_rw_lock_writer_unlock() | 
| 447 |  * on @rw_lock while a #GRWLockWriterLocker exists can lead to undefined | 
| 448 |  * behaviour. | 
| 449 |  * | 
| 450 |  * No allocation is performed, it is equivalent to a g_rw_lock_writer_lock() call. | 
| 451 |  * | 
| 452 |  * This is intended to be used with g_autoptr().  Note that g_autoptr() | 
| 453 |  * is only available when using GCC or clang, so the following example | 
| 454 |  * will only work with those compilers: | 
| 455 |  * |[ | 
| 456 |  * typedef struct | 
| 457 |  * { | 
| 458 |  *   ... | 
| 459 |  *   GRWLock rw_lock; | 
| 460 |  *   GPtrArray *array; | 
| 461 |  *   ... | 
| 462 |  * } MyObject; | 
| 463 |  * | 
| 464 |  * static gchar * | 
| 465 |  * my_object_get_data (MyObject *self, guint index) | 
| 466 |  * { | 
| 467 |  *   g_autoptr(GRWLockReaderLocker) locker = g_rw_lock_reader_locker_new (&self->rw_lock); | 
| 468 |  * | 
| 469 |  *   // Code with a read lock obtained on rw_lock here | 
| 470 |  * | 
| 471 |  *   if (self->array == NULL) | 
| 472 |  *     // No need to unlock | 
| 473 |  *     return NULL; | 
| 474 |  * | 
| 475 |  *   if (index < self->array->len) | 
| 476 |  *     // No need to unlock | 
| 477 |  *     return g_ptr_array_index (self->array, index); | 
| 478 |  * | 
| 479 |  *   // Optionally early unlock | 
| 480 |  *   g_clear_pointer (&locker, g_rw_lock_reader_locker_free); | 
| 481 |  * | 
| 482 |  *   // Code with rw_lock unlocked here | 
| 483 |  *   return NULL; | 
| 484 |  * } | 
| 485 |  * | 
| 486 |  * static void | 
| 487 |  * my_object_set_data (MyObject *self, guint index, gpointer data) | 
| 488 |  * { | 
| 489 |  *   g_autoptr(GRWLockWriterLocker) locker = g_rw_lock_writer_locker_new (&self->rw_lock); | 
| 490 |  * | 
| 491 |  *   // Code with a write lock obtained on rw_lock here | 
| 492 |  * | 
| 493 |  *   if (self->array == NULL) | 
| 494 |  *     self->array = g_ptr_array_new (); | 
| 495 |  * | 
| 496 |  *   if (cond) | 
| 497 |  *     // No need to unlock | 
| 498 |  *     return; | 
| 499 |  * | 
| 500 |  *   if (index >= self->array->len) | 
| 501 |  *     g_ptr_array_set_size (self->array, index+1); | 
| 502 |  *   g_ptr_array_index (self->array, index) = data; | 
| 503 |  * | 
| 504 |  *   // Optionally early unlock | 
| 505 |  *   g_clear_pointer (&locker, g_rw_lock_writer_locker_free); | 
| 506 |  * | 
| 507 |  *   // Code with rw_lock unlocked here | 
| 508 |  * } | 
| 509 |  * ]| | 
| 510 |  * | 
| 511 |  * Returns: a #GRWLockWriterLocker | 
| 512 |  * Since: 2.62 | 
| 513 |  */ | 
| 514 | G_GNUC_BEGIN_IGNORE_DEPRECATIONS | 
| 515 | GLIB_AVAILABLE_STATIC_INLINE_IN_2_62 | 
| 516 | static inline GRWLockWriterLocker * | 
| 517 | g_rw_lock_writer_locker_new (GRWLock *rw_lock) | 
| 518 | { | 
| 519 |   g_rw_lock_writer_lock (rw_lock); | 
| 520 |   return (GRWLockWriterLocker *) rw_lock; | 
| 521 | } | 
| 522 | G_GNUC_END_IGNORE_DEPRECATIONS | 
| 523 |  | 
| 524 | /** | 
| 525 |  * g_rw_lock_writer_locker_free: | 
| 526 |  * @locker: a GRWLockWriterLocker | 
| 527 |  * | 
| 528 |  * Release a write lock on @locker's read-write lock. See | 
| 529 |  * g_rw_lock_writer_locker_new() for details. | 
| 530 |  * | 
| 531 |  * No memory is freed, it is equivalent to a g_rw_lock_writer_unlock() call. | 
| 532 |  * | 
| 533 |  * Since: 2.62 | 
| 534 |  */ | 
| 535 | G_GNUC_BEGIN_IGNORE_DEPRECATIONS | 
| 536 | GLIB_AVAILABLE_STATIC_INLINE_IN_2_62 | 
| 537 | static inline void | 
| 538 | g_rw_lock_writer_locker_free (GRWLockWriterLocker *locker) | 
| 539 | { | 
| 540 |   g_rw_lock_writer_unlock ((GRWLock *) locker); | 
| 541 | } | 
| 542 | G_GNUC_END_IGNORE_DEPRECATIONS | 
| 543 |  | 
| 544 | /** | 
| 545 |  * GRWLockReaderLocker: | 
| 546 |  * | 
| 547 |  * Opaque type. See g_rw_lock_reader_locker_new() for details. | 
| 548 |  * Since: 2.62 | 
| 549 |  */ | 
| 550 | typedef void GRWLockReaderLocker; | 
| 551 |  | 
| 552 | /** | 
| 553 |  * g_rw_lock_reader_locker_new: | 
| 554 |  * @rw_lock: a #GRWLock | 
| 555 |  * | 
| 556 |  * Obtain a read lock on @rw_lock and return a new #GRWLockReaderLocker. | 
| 557 |  * Unlock with g_rw_lock_reader_locker_free(). Using g_rw_lock_reader_unlock() | 
| 558 |  * on @rw_lock while a #GRWLockReaderLocker exists can lead to undefined | 
| 559 |  * behaviour. | 
| 560 |  * | 
| 561 |  * No allocation is performed, it is equivalent to a g_rw_lock_reader_lock() call. | 
| 562 |  * | 
| 563 |  * This is intended to be used with g_autoptr(). For a code sample, see | 
| 564 |  * g_rw_lock_writer_locker_new(). | 
| 565 |  * | 
| 566 |  * Returns: a #GRWLockReaderLocker | 
| 567 |  * Since: 2.62 | 
| 568 |  */ | 
| 569 | G_GNUC_BEGIN_IGNORE_DEPRECATIONS | 
| 570 | GLIB_AVAILABLE_STATIC_INLINE_IN_2_62 | 
| 571 | static inline GRWLockReaderLocker * | 
| 572 | g_rw_lock_reader_locker_new (GRWLock *rw_lock) | 
| 573 | { | 
| 574 |   g_rw_lock_reader_lock (rw_lock); | 
| 575 |   return (GRWLockReaderLocker *) rw_lock; | 
| 576 | } | 
| 577 | G_GNUC_END_IGNORE_DEPRECATIONS | 
| 578 |  | 
| 579 | /** | 
| 580 |  * g_rw_lock_reader_locker_free: | 
| 581 |  * @locker: a GRWLockReaderLocker | 
| 582 |  * | 
| 583 |  * Release a read lock on @locker's read-write lock. See | 
| 584 |  * g_rw_lock_reader_locker_new() for details. | 
| 585 |  * | 
| 586 |  * No memory is freed, it is equivalent to a g_rw_lock_reader_unlock() call. | 
| 587 |  * | 
| 588 |  * Since: 2.62 | 
| 589 |  */ | 
| 590 | G_GNUC_BEGIN_IGNORE_DEPRECATIONS | 
| 591 | GLIB_AVAILABLE_STATIC_INLINE_IN_2_62 | 
| 592 | static inline void | 
| 593 | g_rw_lock_reader_locker_free (GRWLockReaderLocker *locker) | 
| 594 | { | 
| 595 |   g_rw_lock_reader_unlock ((GRWLock *) locker); | 
| 596 | } | 
| 597 | G_GNUC_END_IGNORE_DEPRECATIONS | 
| 598 |  | 
| 599 | G_END_DECLS | 
| 600 |  | 
| 601 | #endif /* __G_THREAD_H__ */ | 
| 602 |  |