source: trunk/third/glib2/glib/gthread.c @ 18159

Revision 18159, 20.5 KB checked in by ghudson, 22 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r18158, which included commits to RCS files with non-trunk default branches.
Line 
1/* GLIB - Library of useful routines for C programming
2 * Copyright (C) 1995-1997  Peter Mattis, Spencer Kimball and Josh MacDonald
3 *
4 * gmutex.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, write to the
20 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21 * Boston, MA 02111-1307, USA.
22 */
23
24/*
25 * Modified by the GLib Team and others 1997-2000.  See the AUTHORS
26 * file for a list of people on the GLib Team.  See the ChangeLog
27 * files for a list of changes.  These files are distributed with
28 * GLib at ftp://ftp.gtk.org/pub/gtk/.
29 */
30
31/*
32 * MT safe
33 */
34
35#include "config.h"
36
37#ifdef G_THREAD_USE_PID_SURROGATE
38#include <sys/types.h>
39#include <sys/time.h>
40#include <sys/resource.h>
41#include <errno.h>
42#endif /* G_THREAD_USE_PID_SURROGATE */
43
44#ifdef HAVE_UNISTD_H
45#include <unistd.h>
46#endif
47
48#include <string.h>
49
50#include "glib.h"
51
52
53#if GLIB_SIZEOF_SYSTEM_THREAD == SIZEOF_VOID_P
54# define g_system_thread_equal_simple(thread1, thread2)                 \
55   ((thread1).dummy_pointer == (thread2).dummy_pointer)
56# define g_system_thread_assign(dest, src)                              \
57   ((dest).dummy_pointer = (src).dummy_pointer)
58#else /* GLIB_SIZEOF_SYSTEM_THREAD != SIZEOF_VOID_P */
59# define g_system_thread_equal_simple(thread1, thread2)                 \
60   (memcmp (&(thread1), &(thread2), GLIB_SIZEOF_SYSTEM_THREAD) == 0)
61# define g_system_thread_assign(dest, src)                              \
62   (memcpy (&(dest), &(src), GLIB_SIZEOF_SYSTEM_THREAD))
63#endif /* GLIB_SIZEOF_SYSTEM_THREAD == SIZEOF_VOID_P */
64
65#define g_system_thread_equal(thread1, thread2)                         \
66  (g_thread_functions_for_glib_use.thread_equal ?                       \
67   g_thread_functions_for_glib_use.thread_equal (&(thread1), &(thread2)) :\
68   g_system_thread_equal_simple((thread1), (thread2)))
69
70GQuark
71g_thread_error_quark (void)
72{
73  static GQuark quark;
74  if (!quark)
75    quark = g_quark_from_static_string ("g_thread_error");
76  return quark;
77}
78
79/* Keep this in sync with GRealThread in gmain.c! */
80typedef struct _GRealThread GRealThread;
81struct  _GRealThread
82{
83  GThread thread;
84  gpointer private_data;
85  gpointer retval;
86  GSystemThread system_thread;
87#ifdef G_THREAD_USE_PID_SURROGATE
88  pid_t pid;
89#endif /* G_THREAD_USE_PID_SURROGATE */
90};
91
92#ifdef G_THREAD_USE_PID_SURROGATE
93static gint priority_map[4];
94static gboolean prio_warned = FALSE;
95# define SET_PRIO(pid, prio) G_STMT_START{                              \
96  gint error = setpriority (PRIO_PROCESS, (pid), priority_map[prio]);   \
97  if (error == -1 && errno == EACCES && !prio_warned)                   \
98    {                                                                   \
99      prio_warned = TRUE;                                               \
100      g_warning ("Priorities can only be increased by root.");          \
101    }                                                                   \
102  }G_STMT_END
103#endif /* G_THREAD_USE_PID_SURROGATE */
104
105typedef struct _GStaticPrivateNode GStaticPrivateNode;
106struct _GStaticPrivateNode
107{
108  gpointer       data;
109  GDestroyNotify destroy;
110};
111
112static void g_thread_cleanup (gpointer data);
113static void g_thread_fail (void);
114
115/* Global variables */
116
117static GSystemThread zero_thread; /* This is initialized to all zero */
118gboolean g_thread_use_default_impl = TRUE;
119gboolean g_threads_got_initialized = FALSE;
120
121#if defined(G_PLATFORM_WIN32) && defined(__GNUC__)
122__declspec(dllexport)
123#endif
124GThreadFunctions g_thread_functions_for_glib_use = {
125  (GMutex*(*)())g_thread_fail,                 /* mutex_new */
126  NULL,                                        /* mutex_lock */
127  NULL,                                        /* mutex_trylock */
128  NULL,                                        /* mutex_unlock */
129  NULL,                                        /* mutex_free */
130  (GCond*(*)())g_thread_fail,                  /* cond_new */
131  NULL,                                        /* cond_signal */
132  NULL,                                        /* cond_broadcast */
133  NULL,                                        /* cond_wait */
134  NULL,                                        /* cond_timed_wait  */
135  NULL,                                        /* cond_free */
136  (GPrivate*(*)(GDestroyNotify))g_thread_fail, /* private_new */
137  NULL,                                        /* private_get */
138  NULL,                                        /* private_set */
139  (void(*)(GThreadFunc, gpointer, gulong,
140           gboolean, gboolean, GThreadPriority,
141           gpointer, GError**))g_thread_fail,  /* thread_create */
142  NULL,                                        /* thread_yield */
143  NULL,                                        /* thread_join */
144  NULL,                                        /* thread_exit */
145  NULL,                                        /* thread_set_priority */
146  NULL                                         /* thread_self */
147};
148
149/* Local data */
150
151static GMutex   *g_mutex_protect_static_mutex_allocation = NULL;
152static GPrivate *g_thread_specific_private = NULL;
153static GSList   *g_thread_all_threads = NULL;
154static GSList   *g_thread_free_indeces = NULL;
155
156G_LOCK_DEFINE_STATIC (g_thread);
157
158/* This must be called only once, before any threads are created.
159 * It will only be called from g_thread_init() in -lgthread.
160 */
161void
162g_mutex_init (void)
163{
164  GRealThread* main_thread;
165 
166  /* We let the main thread (the one that calls g_thread_init) inherit
167   * the data, that it set before calling g_thread_init
168   */
169  main_thread = (GRealThread*) g_thread_self ();
170
171  g_thread_specific_private = g_private_new (g_thread_cleanup);
172  G_THREAD_UF (private_set, (g_thread_specific_private, main_thread));
173  G_THREAD_UF (thread_self, (&main_thread->system_thread));
174
175  g_mutex_protect_static_mutex_allocation = g_mutex_new ();
176
177#ifdef G_THREAD_USE_PID_SURROGATE
178  priority_map[G_THREAD_PRIORITY_NORMAL] =
179    getpriority (PRIO_PROCESS, (getpid ()));
180  priority_map[G_THREAD_PRIORITY_LOW] =
181    MIN (20, priority_map[G_THREAD_PRIORITY_NORMAL] + 10);
182  priority_map[G_THREAD_PRIORITY_HIGH] =
183    MAX (-20, priority_map[G_THREAD_PRIORITY_NORMAL] - 10);
184  priority_map[G_THREAD_PRIORITY_URGENT] =
185    MAX (-20, priority_map[G_THREAD_PRIORITY_NORMAL] - 15);
186#endif /* G_THREAD_USE_PID_SURROGATE */
187}
188
189void
190g_static_mutex_init (GStaticMutex *mutex)
191{
192  static GStaticMutex init_mutex = G_STATIC_MUTEX_INIT;
193
194  g_return_if_fail (mutex);
195
196  *mutex = init_mutex;
197}
198
199GMutex *
200g_static_mutex_get_mutex_impl (GMutex** mutex)
201{
202  if (!g_thread_supported ())
203    return NULL;
204
205  g_assert (g_mutex_protect_static_mutex_allocation);
206
207  g_mutex_lock (g_mutex_protect_static_mutex_allocation);
208
209  if (!(*mutex))
210    *mutex = g_mutex_new ();
211
212  g_mutex_unlock (g_mutex_protect_static_mutex_allocation);
213 
214  return *mutex;
215}
216
217void
218g_static_mutex_free (GStaticMutex* mutex)
219{
220  GMutex **runtime_mutex;
221 
222  g_return_if_fail (mutex);
223
224  /* The runtime_mutex is the first (or only) member of GStaticMutex,
225   * see both versions (of glibconfig.h) in configure.in */
226  runtime_mutex = ((GMutex**)mutex);
227 
228  if (*runtime_mutex)
229    g_mutex_free (*runtime_mutex);
230
231  *runtime_mutex = NULL;
232}
233
234void     
235g_static_rec_mutex_init (GStaticRecMutex *mutex)
236{
237  static GStaticRecMutex init_mutex = G_STATIC_REC_MUTEX_INIT;
238 
239  g_return_if_fail (mutex);
240
241  *mutex = init_mutex;
242}
243
244void
245g_static_rec_mutex_lock (GStaticRecMutex* mutex)
246{
247  GSystemThread self;
248
249  g_return_if_fail (mutex);
250
251  if (!g_thread_supported ())
252    return;
253
254  G_THREAD_UF (thread_self, (&self));
255
256  if (g_system_thread_equal (self, mutex->owner))
257    {
258      mutex->depth++;
259      return;
260    }
261  g_static_mutex_lock (&mutex->mutex);
262  g_system_thread_assign (mutex->owner, self);
263  mutex->depth = 1;
264}
265
266gboolean
267g_static_rec_mutex_trylock (GStaticRecMutex* mutex)
268{
269  GSystemThread self;
270
271  g_return_val_if_fail (mutex, FALSE);
272
273  if (!g_thread_supported ())
274    return TRUE;
275
276  G_THREAD_UF (thread_self, (&self));
277
278  if (g_system_thread_equal (self, mutex->owner))
279    {
280      mutex->depth++;
281      return TRUE;
282    }
283
284  if (!g_static_mutex_trylock (&mutex->mutex))
285    return FALSE;
286
287  g_system_thread_assign (mutex->owner, self);
288  mutex->depth = 1;
289  return TRUE;
290}
291
292void
293g_static_rec_mutex_unlock (GStaticRecMutex* mutex)
294{
295  g_return_if_fail (mutex);
296
297  if (!g_thread_supported ())
298    return;
299
300  if (mutex->depth > 1)
301    {
302      mutex->depth--;
303      return;
304    }
305  g_system_thread_assign (mutex->owner, zero_thread);
306  g_static_mutex_unlock (&mutex->mutex); 
307}
308
309void
310g_static_rec_mutex_lock_full   (GStaticRecMutex *mutex,
311                                guint            depth)
312{
313  GSystemThread self;
314  g_return_if_fail (mutex);
315
316  if (!g_thread_supported ())
317    return;
318
319  G_THREAD_UF (thread_self, (&self));
320
321  if (g_system_thread_equal (self, mutex->owner))
322    {
323      mutex->depth += depth;
324      return;
325    }
326  g_static_mutex_lock (&mutex->mutex);
327  g_system_thread_assign (mutex->owner, self);
328  mutex->depth = depth;
329}
330
331guint   
332g_static_rec_mutex_unlock_full (GStaticRecMutex *mutex)
333{
334  guint depth;
335
336  g_return_val_if_fail (mutex, 0);
337
338  if (!g_thread_supported ())
339    return 1;
340
341  depth = mutex->depth;
342
343  g_system_thread_assign (mutex->owner, zero_thread);
344  mutex->depth = 0;
345  g_static_mutex_unlock (&mutex->mutex);
346
347  return depth;
348}
349
350void
351g_static_rec_mutex_free (GStaticRecMutex *mutex)
352{
353  g_return_if_fail (mutex);
354
355  g_static_mutex_free (&mutex->mutex);
356}
357
358void     
359g_static_private_init (GStaticPrivate *private_key)
360{
361  private_key->index = 0;
362}
363
364gpointer
365g_static_private_get (GStaticPrivate *private_key)
366{
367  GRealThread *self = (GRealThread*) g_thread_self ();
368  GArray *array;
369
370  array = self->private_data;
371  if (!array)
372    return NULL;
373
374  if (!private_key->index)
375    return NULL;
376  else if (private_key->index <= array->len)
377    return g_array_index (array, GStaticPrivateNode,
378                          private_key->index - 1).data;
379  else
380    return NULL;
381}
382
383void
384g_static_private_set (GStaticPrivate *private_key,
385                      gpointer        data,
386                      GDestroyNotify  notify)
387{
388  GRealThread *self = (GRealThread*) g_thread_self ();
389  GArray *array;
390  static guint next_index = 0;
391  GStaticPrivateNode *node;
392
393  array = self->private_data;
394  if (!array)
395    {
396      array = g_array_new (FALSE, TRUE, sizeof (GStaticPrivateNode));
397      self->private_data = array;
398    }
399
400  if (!private_key->index)
401    {
402      G_LOCK (g_thread);
403
404      if (!private_key->index)
405        {
406          if (g_thread_free_indeces)
407            {
408              private_key->index =
409                GPOINTER_TO_UINT (g_thread_free_indeces->data);
410              g_thread_free_indeces =
411                g_slist_delete_link (g_thread_free_indeces,
412                                     g_thread_free_indeces);
413            }
414          else
415            private_key->index = ++next_index;
416        }
417
418      G_UNLOCK (g_thread);
419    }
420
421  if (private_key->index > array->len)
422    g_array_set_size (array, private_key->index);
423
424  node = &g_array_index (array, GStaticPrivateNode, private_key->index - 1);
425  if (node->destroy)
426    {
427      gpointer ddata = node->data;
428      GDestroyNotify ddestroy = node->destroy;
429
430      node->data = data;
431      node->destroy = notify;
432
433      ddestroy (ddata);
434    }
435  else
436    {
437      node->data = data;
438      node->destroy = notify;
439    }
440}
441
442void     
443g_static_private_free (GStaticPrivate *private_key)
444{
445  guint index = private_key->index;
446  GSList *list;
447
448  if (!index)
449    return;
450 
451  private_key->index = 0;
452
453  G_LOCK (g_thread);
454  list =  g_thread_all_threads;
455  while (list)
456    {
457      GRealThread *thread = list->data;
458      GArray *array = thread->private_data;
459      list = list->next;
460
461      if (array && index <= array->len)
462        {
463          GStaticPrivateNode *node = &g_array_index (array,
464                                                     GStaticPrivateNode,
465                                                     index - 1);
466          gpointer ddata = node->data;
467          GDestroyNotify ddestroy = node->destroy;
468
469          node->data = NULL;
470          node->destroy = NULL;
471
472          if (ddestroy)
473            {
474              G_UNLOCK (g_thread);
475              ddestroy (ddata);
476              G_LOCK (g_thread);
477              }
478        }
479    }
480  g_thread_free_indeces = g_slist_prepend (g_thread_free_indeces,
481                                           GUINT_TO_POINTER (index));
482  G_UNLOCK (g_thread);
483}
484
485static void
486g_thread_cleanup (gpointer data)
487{
488  if (data)
489    {
490      GRealThread* thread = data;
491      if (thread->private_data)
492        {
493          GArray* array = thread->private_data;
494          guint i;
495         
496          for (i = 0; i < array->len; i++ )
497            {
498              GStaticPrivateNode *node =
499                &g_array_index (array, GStaticPrivateNode, i);
500              if (node->destroy)
501                node->destroy (node->data);
502            }
503          g_array_free (array, TRUE);
504        }
505
506      /* We only free the thread structure, if it isn't joinable. If
507         it is, the structure is freed in g_thread_join */
508      if (!thread->thread.joinable)
509        {
510          G_LOCK (g_thread);
511          g_thread_all_threads = g_slist_remove (g_thread_all_threads, data);
512          G_UNLOCK (g_thread);
513         
514          /* Just to make sure, this isn't used any more */
515          g_system_thread_assign (thread->system_thread, zero_thread);
516          g_free (thread);
517        }
518    }
519}
520
521static void
522g_thread_fail (void)
523{
524  g_error ("The thread system is not yet initialized.");
525}
526
527static gpointer
528g_thread_create_proxy (gpointer data)
529{
530  GRealThread* thread = data;
531
532  g_assert (data);
533
534#ifdef G_THREAD_USE_PID_SURROGATE
535  thread->pid = getpid ();
536#endif /* G_THREAD_USE_PID_SURROGATE */
537
538  /* This has to happen before G_LOCK, as that might call g_thread_self */
539  g_private_set (g_thread_specific_private, data);
540
541  /* the lock makes sure, that thread->system_thread is written,
542     before thread->thread.func is called. See g_thread_create. */
543  G_LOCK (g_thread);
544  G_UNLOCK (g_thread);
545 
546#ifdef G_THREAD_USE_PID_SURROGATE
547  if (g_thread_use_default_impl)
548    SET_PRIO (thread->pid, thread->thread.priority);
549#endif /* G_THREAD_USE_PID_SURROGATE */
550
551  thread->retval = thread->thread.func (thread->thread.data);
552
553  return NULL;
554}
555
556GThread*
557g_thread_create_full (GThreadFunc                func,
558                      gpointer           data,
559                      gulong             stack_size,
560                      gboolean           joinable,
561                      gboolean           bound,
562                      GThreadPriority    priority,
563                      GError                **error)
564{
565  GRealThread* result;
566  GError *local_error = NULL;
567  g_return_val_if_fail (func, NULL);
568  g_return_val_if_fail (priority >= G_THREAD_PRIORITY_LOW, NULL);
569  g_return_val_if_fail (priority <= G_THREAD_PRIORITY_URGENT, NULL);
570 
571  result = g_new (GRealThread, 1);
572
573  result->thread.joinable = joinable;
574  result->thread.priority = priority;
575  result->thread.func = func;
576  result->thread.data = data;
577  result->private_data = NULL;
578  G_LOCK (g_thread);
579  G_THREAD_UF (thread_create, (g_thread_create_proxy, result,
580                               stack_size, joinable, bound, priority,
581                               &result->system_thread, &local_error));
582  g_thread_all_threads = g_slist_prepend (g_thread_all_threads, result);
583  G_UNLOCK (g_thread);
584
585  if (local_error)
586    {
587      g_propagate_error (error, local_error);
588      g_free (result);
589      return NULL;
590    }
591
592  return (GThread*) result;
593}
594
595void
596g_thread_exit (gpointer retval)
597{
598  GRealThread* real = (GRealThread*) g_thread_self ();
599  real->retval = retval;
600  G_THREAD_CF (thread_exit, (void)0, ());
601}
602
603gpointer
604g_thread_join (GThread* thread)
605{
606  GRealThread* real = (GRealThread*) thread;
607  gpointer retval;
608
609  g_return_val_if_fail (thread, NULL);
610  g_return_val_if_fail (thread->joinable, NULL);
611  g_return_val_if_fail (!g_system_thread_equal (real->system_thread,
612                                                zero_thread), NULL);
613
614  G_THREAD_UF (thread_join, (&real->system_thread));
615
616  retval = real->retval;
617
618  G_LOCK (g_thread);
619  g_thread_all_threads = g_slist_remove (g_thread_all_threads, thread);
620  G_UNLOCK (g_thread);
621
622  /* Just to make sure, this isn't used any more */
623  thread->joinable = 0;
624  g_system_thread_assign (real->system_thread, zero_thread);
625
626  /* the thread structure for non-joinable threads is freed upon
627     thread end. We free the memory here. This will leave a loose end,
628     if a joinable thread is not joined. */
629
630  g_free (thread);
631
632  return retval;
633}
634
635void
636g_thread_set_priority (GThread* thread,
637                       GThreadPriority priority)
638{
639  GRealThread* real = (GRealThread*) thread;
640
641  g_return_if_fail (thread);
642  g_return_if_fail (!g_system_thread_equal (real->system_thread, zero_thread));
643  g_return_if_fail (priority >= G_THREAD_PRIORITY_LOW);
644  g_return_if_fail (priority <= G_THREAD_PRIORITY_URGENT);
645
646  thread->priority = priority;
647
648#ifdef G_THREAD_USE_PID_SURROGATE
649  if (g_thread_use_default_impl)
650    SET_PRIO (real->pid, priority);
651  else
652#endif /* G_THREAD_USE_PID_SURROGATE */
653    G_THREAD_CF (thread_set_priority, (void)0,
654                 (&real->system_thread, priority));
655}
656
657GThread*
658g_thread_self (void)
659{
660  GRealThread* thread = g_private_get (g_thread_specific_private);
661
662  if (!thread)
663    { 
664      /* If no thread data is available, provide and set one.  This
665         can happen for the main thread and for threads, that are not
666         created by GLib. */
667      thread = g_new (GRealThread, 1);
668      thread->thread.joinable = FALSE; /* This is a save guess */
669      thread->thread.priority = G_THREAD_PRIORITY_NORMAL; /* This is
670                                                             just a guess */
671      thread->thread.func = NULL;
672      thread->thread.data = NULL;
673      thread->private_data = NULL;
674
675      if (g_thread_supported ())
676        G_THREAD_UF (thread_self, (&thread->system_thread));
677
678#ifdef G_THREAD_USE_PID_SURROGATE
679      thread->pid = getpid ();
680#endif /* G_THREAD_USE_PID_SURROGATE */
681     
682      g_private_set (g_thread_specific_private, thread);
683     
684      G_LOCK (g_thread);
685      g_thread_all_threads = g_slist_prepend (g_thread_all_threads, thread);
686      G_UNLOCK (g_thread);
687    }
688 
689  return (GThread*)thread;
690}
691
692void
693g_static_rw_lock_init (GStaticRWLock* lock)
694{
695  static GStaticRWLock init_lock = G_STATIC_RW_LOCK_INIT;
696
697  g_return_if_fail (lock);
698
699  *lock = init_lock;
700}
701
702static void inline
703g_static_rw_lock_wait (GCond** cond, GStaticMutex* mutex)
704{
705  if (!*cond)
706      *cond = g_cond_new ();
707  g_cond_wait (*cond, g_static_mutex_get_mutex (mutex));
708}
709
710static void inline
711g_static_rw_lock_signal (GStaticRWLock* lock)
712{
713  if (lock->want_to_write && lock->write_cond)
714    g_cond_signal (lock->write_cond);
715  else if (lock->want_to_read && lock->read_cond)
716    g_cond_broadcast (lock->read_cond);
717}
718
719void
720g_static_rw_lock_reader_lock (GStaticRWLock* lock)
721{
722  g_return_if_fail (lock);
723
724  if (!g_threads_got_initialized)
725    return;
726
727  g_static_mutex_lock (&lock->mutex);
728  lock->want_to_read++;
729  while (lock->have_writer || lock->want_to_write)
730    g_static_rw_lock_wait (&lock->read_cond, &lock->mutex);
731  lock->want_to_read--;
732  lock->read_counter++;
733  g_static_mutex_unlock (&lock->mutex);
734}
735
736gboolean
737g_static_rw_lock_reader_trylock (GStaticRWLock* lock)
738{
739  gboolean ret_val = FALSE;
740
741  g_return_val_if_fail (lock, FALSE);
742
743  if (!g_threads_got_initialized)
744    return TRUE;
745
746  g_static_mutex_lock (&lock->mutex);
747  if (!lock->have_writer && !lock->want_to_write)
748    {
749      lock->read_counter++;
750      ret_val = TRUE;
751    }
752  g_static_mutex_unlock (&lock->mutex);
753  return ret_val;
754}
755
756void
757g_static_rw_lock_reader_unlock  (GStaticRWLock* lock)
758{
759  g_return_if_fail (lock);
760
761  if (!g_threads_got_initialized)
762    return;
763
764  g_static_mutex_lock (&lock->mutex);
765  lock->read_counter--;
766  if (lock->read_counter == 0)
767    g_static_rw_lock_signal (lock);
768  g_static_mutex_unlock (&lock->mutex);
769}
770
771void
772g_static_rw_lock_writer_lock (GStaticRWLock* lock)
773{
774  g_return_if_fail (lock);
775
776  if (!g_threads_got_initialized)
777    return;
778
779  g_static_mutex_lock (&lock->mutex);
780  lock->want_to_write++;
781  while (lock->have_writer || lock->read_counter)
782    g_static_rw_lock_wait (&lock->write_cond, &lock->mutex);
783  lock->want_to_write--;
784  lock->have_writer = TRUE;
785  g_static_mutex_unlock (&lock->mutex);
786}
787
788gboolean
789g_static_rw_lock_writer_trylock (GStaticRWLock* lock)
790{
791  gboolean ret_val = FALSE;
792
793  g_return_val_if_fail (lock, FALSE);
794 
795  if (!g_threads_got_initialized)
796    return TRUE;
797
798  g_static_mutex_lock (&lock->mutex);
799  if (!lock->have_writer && !lock->read_counter)
800    {
801      lock->have_writer = TRUE;
802      ret_val = TRUE;
803    }
804  g_static_mutex_unlock (&lock->mutex);
805  return ret_val;
806}
807
808void
809g_static_rw_lock_writer_unlock (GStaticRWLock* lock)
810{
811  g_return_if_fail (lock);
812 
813  if (!g_threads_got_initialized)
814    return;
815
816  g_static_mutex_lock (&lock->mutex);
817  lock->have_writer = FALSE;
818  g_static_rw_lock_signal (lock);
819  g_static_mutex_unlock (&lock->mutex);
820}
821
822void
823g_static_rw_lock_free (GStaticRWLock* lock)
824{
825  g_return_if_fail (lock);
826 
827  if (lock->read_cond)
828    {
829      g_cond_free (lock->read_cond);
830      lock->read_cond = NULL;
831    }
832  if (lock->write_cond)
833    {
834      g_cond_free (lock->write_cond);
835      lock->write_cond = NULL;
836    }
837  g_static_mutex_free (&lock->mutex);
838}
Note: See TracBrowser for help on using the repository browser.