source: trunk/third/glib2/glib/gthread.h @ 20721

Revision 20721, 15.3 KB checked in by ghudson, 20 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r20720, 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 * 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 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but 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, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
18 */
19
20/*
21 * Modified by the GLib Team and others 1997-2000.  See the AUTHORS
22 * file for a list of people on the GLib Team.  See the ChangeLog
23 * files for a list of changes.  These files are distributed with
24 * GLib at ftp://ftp.gtk.org/pub/gtk/.
25 */
26
27#ifndef __G_THREAD_H__
28#define __G_THREAD_H__
29
30#include <glib/gerror.h>
31#include <glib/gtypes.h>
32#include <glib/gatomic.h>  /* for g_atomic_pointer_get */
33
34G_BEGIN_DECLS
35
36/* GLib Thread support
37 */
38
39extern GQuark g_thread_error_quark (void);
40#define G_THREAD_ERROR g_thread_error_quark ()
41
42typedef enum
43{
44  G_THREAD_ERROR_AGAIN /* Resource temporarily unavailable */
45} GThreadError;
46
47typedef gpointer (*GThreadFunc) (gpointer data);
48
49typedef enum
50{
51  G_THREAD_PRIORITY_LOW,
52  G_THREAD_PRIORITY_NORMAL,
53  G_THREAD_PRIORITY_HIGH,
54  G_THREAD_PRIORITY_URGENT
55} GThreadPriority;
56
57typedef struct _GThread         GThread;
58struct  _GThread
59{
60  /*< private >*/
61  GThreadFunc func;
62  gpointer data;
63  gboolean joinable;
64  GThreadPriority priority;
65};
66
67typedef struct _GMutex          GMutex;
68typedef struct _GCond           GCond;
69typedef struct _GPrivate        GPrivate;
70typedef struct _GStaticPrivate  GStaticPrivate;
71
72typedef struct _GThreadFunctions GThreadFunctions;
73struct _GThreadFunctions
74{
75  GMutex*  (*mutex_new)           (void);
76  void     (*mutex_lock)          (GMutex               *mutex);
77  gboolean (*mutex_trylock)       (GMutex               *mutex);
78  void     (*mutex_unlock)        (GMutex               *mutex);
79  void     (*mutex_free)          (GMutex               *mutex);
80  GCond*   (*cond_new)            (void);
81  void     (*cond_signal)         (GCond                *cond);
82  void     (*cond_broadcast)      (GCond                *cond);
83  void     (*cond_wait)           (GCond                *cond,
84                                   GMutex               *mutex);
85  gboolean (*cond_timed_wait)     (GCond                *cond,
86                                   GMutex               *mutex,
87                                   GTimeVal             *end_time);
88  void      (*cond_free)          (GCond                *cond);
89  GPrivate* (*private_new)        (GDestroyNotify        destructor);
90  gpointer  (*private_get)        (GPrivate             *private_key);
91  void      (*private_set)        (GPrivate             *private_key,
92                                   gpointer              data);
93  void      (*thread_create)      (GThreadFunc           func,
94                                   gpointer              data,
95                                   gulong                stack_size,
96                                   gboolean              joinable,
97                                   gboolean              bound,
98                                   GThreadPriority       priority,
99                                   gpointer              thread,
100                                   GError              **error);
101  void      (*thread_yield)       (void);
102  void      (*thread_join)        (gpointer              thread);
103  void      (*thread_exit)        (void);
104  void      (*thread_set_priority)(gpointer              thread,
105                                   GThreadPriority       priority);
106  void      (*thread_self)        (gpointer              thread);
107  gboolean  (*thread_equal)       (gpointer              thread1,
108                                   gpointer              thread2);
109};
110
111GLIB_VAR GThreadFunctions       g_thread_functions_for_glib_use;
112GLIB_VAR gboolean               g_thread_use_default_impl;
113GLIB_VAR gboolean               g_threads_got_initialized;
114
115/* initializes the mutex/cond/private implementation for glib, might
116 * only be called once, and must not be called directly or indirectly
117 * from another glib-function, e.g. as a callback.
118 */
119void    g_thread_init   (GThreadFunctions       *vtable);
120
121/* Errorcheck mutexes. If you define G_ERRORCHECK_MUTEXES, then all
122 * mutexes will check for re-locking and re-unlocking */
123
124/* Initialize thread system with errorcheck mutexes. vtable must be
125 * NULL. Do not call directly. Use #define G_ERRORCHECK_MUTEXES
126 * instead.
127 */
128void    g_thread_init_with_errorcheck_mutexes (GThreadFunctions* vtable);
129
130/* A random number to recognize debug calls to g_mutex_... */
131#define G_MUTEX_DEBUG_MAGIC 0xf8e18ad7
132
133#ifdef G_ERRORCHECK_MUTEXES
134#define g_thread_init(vtable) g_thread_init_with_errorcheck_mutexes (vtable)
135#endif
136
137/* internal function for fallback static mutex implementation */
138GMutex* g_static_mutex_get_mutex_impl   (GMutex **mutex);
139
140#define g_static_mutex_get_mutex_impl_shortcut(mutex) \
141  (g_atomic_pointer_get ((gpointer*)mutex) ? *(mutex) : \
142   g_static_mutex_get_mutex_impl (mutex))
143
144/* shorthands for conditional and unconditional function calls */
145
146#define G_THREAD_UF(op, arglist)                                        \
147    (*g_thread_functions_for_glib_use . op) arglist
148#define G_THREAD_CF(op, fail, arg)                                      \
149    (g_thread_supported () ? G_THREAD_UF (op, arg) : (fail))
150#define G_THREAD_ECF(op, fail, mutex, type)                             \
151    (g_thread_supported () ? ((type(*)(GMutex*, gulong, gchar*))        \
152      (*g_thread_functions_for_glib_use . op))                          \
153     (mutex, G_MUTEX_DEBUG_MAGIC, G_STRLOC) : (fail))
154
155#ifndef G_ERRORCHECK_MUTEXES
156# define g_mutex_lock(mutex)                                            \
157    G_THREAD_CF (mutex_lock,     (void)0, (mutex))
158# define g_mutex_trylock(mutex)                                         \
159    G_THREAD_CF (mutex_trylock,  TRUE,    (mutex))
160# define g_mutex_unlock(mutex)                                          \
161    G_THREAD_CF (mutex_unlock,   (void)0, (mutex))
162# define g_mutex_free(mutex)                                            \
163    G_THREAD_CF (mutex_free,     (void)0, (mutex))
164# define g_cond_wait(cond, mutex)                                       \
165    G_THREAD_CF (cond_wait,      (void)0, (cond, mutex))
166# define g_cond_timed_wait(cond, mutex, abs_time)                       \
167    G_THREAD_CF (cond_timed_wait, TRUE,   (cond, mutex, abs_time))
168#else /* G_ERRORCHECK_MUTEXES */
169# define g_mutex_lock(mutex)                                            \
170    G_THREAD_ECF (mutex_lock,    (void)0, (mutex), void)
171# define g_mutex_trylock(mutex)                                         \
172    G_THREAD_ECF (mutex_trylock, TRUE,    (mutex), gboolean)
173# define g_mutex_unlock(mutex)                                          \
174    G_THREAD_ECF (mutex_unlock,  (void)0, (mutex), void)
175# define g_mutex_free(mutex)                                            \
176    G_THREAD_ECF (mutex_free,    (void)0, (mutex), void)
177# define g_cond_wait(cond, mutex)                                       \
178    (g_thread_supported () ? ((void(*)(GCond*, GMutex*, gulong, gchar*))\
179      g_thread_functions_for_glib_use.cond_wait)                        \
180        (cond, mutex, G_MUTEX_DEBUG_MAGIC, G_STRLOC) : (void) 0)
181# define g_cond_timed_wait(cond, mutex, abs_time)                       \
182    (g_thread_supported () ?                                            \
183      ((gboolean(*)(GCond*, GMutex*, GTimeVal*, gulong, gchar*))        \
184        g_thread_functions_for_glib_use.cond_timed_wait)                \
185          (cond, mutex, abs_time, G_MUTEX_DEBUG_MAGIC, G_STRLOC) : TRUE)
186#endif /* G_ERRORCHECK_MUTEXES */
187
188#define g_thread_supported()    (g_threads_got_initialized)
189#define g_mutex_new()            G_THREAD_UF (mutex_new,      ())
190#define g_cond_new()             G_THREAD_UF (cond_new,       ())
191#define g_cond_signal(cond)      G_THREAD_CF (cond_signal,    (void)0, (cond))
192#define g_cond_broadcast(cond)   G_THREAD_CF (cond_broadcast, (void)0, (cond))
193#define g_cond_free(cond)        G_THREAD_CF (cond_free,      (void)0, (cond))
194#define g_private_new(destructor) G_THREAD_UF (private_new, (destructor))
195#define g_private_get(private_key) G_THREAD_CF (private_get, \
196                                                ((gpointer)private_key), \
197                                                (private_key))
198#define g_private_set(private_key, value) G_THREAD_CF (private_set, \
199                                                       (void) (private_key = \
200                                                        (GPrivate*) (value)), \
201                                                       (private_key, value))
202#define g_thread_yield()              G_THREAD_CF (thread_yield, (void)0, ())
203
204#define g_thread_create(func, data, joinable, error)                    \
205  (g_thread_create_full (func, data, 0, joinable, FALSE,                \
206                         G_THREAD_PRIORITY_NORMAL, error))
207
208GThread* g_thread_create_full  (GThreadFunc            func,
209                                gpointer               data,
210                                gulong                 stack_size,
211                                gboolean               joinable,
212                                gboolean               bound,
213                                GThreadPriority        priority,
214                                GError               **error);
215GThread* g_thread_self         (void);
216void     g_thread_exit         (gpointer               retval);
217gpointer g_thread_join         (GThread               *thread);
218
219void     g_thread_set_priority (GThread               *thread,
220                                GThreadPriority        priority);
221
222/* GStaticMutexes can be statically initialized with the value
223 * G_STATIC_MUTEX_INIT, and then they can directly be used, that is
224 * much easier, than having to explicitly allocate the mutex before
225 * use
226 */
227#define g_static_mutex_lock(mutex) \
228    g_mutex_lock (g_static_mutex_get_mutex (mutex))
229#define g_static_mutex_trylock(mutex) \
230    g_mutex_trylock (g_static_mutex_get_mutex (mutex))
231#define g_static_mutex_unlock(mutex) \
232    g_mutex_unlock (g_static_mutex_get_mutex (mutex))
233void g_static_mutex_init (GStaticMutex *mutex);
234void g_static_mutex_free (GStaticMutex *mutex);
235
236struct _GStaticPrivate
237{
238  /*< private >*/
239  guint index;
240};
241#define G_STATIC_PRIVATE_INIT { 0 }
242void     g_static_private_init           (GStaticPrivate   *private_key);
243gpointer g_static_private_get            (GStaticPrivate   *private_key);
244void     g_static_private_set            (GStaticPrivate   *private_key,
245                                          gpointer          data,
246                                          GDestroyNotify    notify);
247void     g_static_private_free           (GStaticPrivate   *private_key);
248
249typedef struct _GStaticRecMutex GStaticRecMutex;
250struct _GStaticRecMutex
251{
252  /*< private >*/
253  GStaticMutex mutex;
254  guint depth;
255  GSystemThread owner;
256};
257
258#define G_STATIC_REC_MUTEX_INIT { G_STATIC_MUTEX_INIT }
259void     g_static_rec_mutex_init        (GStaticRecMutex *mutex);
260void     g_static_rec_mutex_lock        (GStaticRecMutex *mutex);
261gboolean g_static_rec_mutex_trylock     (GStaticRecMutex *mutex);
262void     g_static_rec_mutex_unlock      (GStaticRecMutex *mutex);
263void     g_static_rec_mutex_lock_full   (GStaticRecMutex *mutex,
264                                         guint            depth);
265guint    g_static_rec_mutex_unlock_full (GStaticRecMutex *mutex);
266void     g_static_rec_mutex_free        (GStaticRecMutex *mutex);
267
268typedef struct _GStaticRWLock GStaticRWLock;
269struct _GStaticRWLock
270{
271  /*< private >*/
272  GStaticMutex mutex;
273  GCond *read_cond;
274  GCond *write_cond;
275  guint read_counter;
276  gboolean have_writer;
277  guint want_to_read;
278  guint want_to_write;
279};
280
281#define G_STATIC_RW_LOCK_INIT { G_STATIC_MUTEX_INIT, NULL, NULL, 0, FALSE, 0, 0 }
282
283void      g_static_rw_lock_init           (GStaticRWLock* lock);
284void      g_static_rw_lock_reader_lock    (GStaticRWLock* lock);
285gboolean  g_static_rw_lock_reader_trylock (GStaticRWLock* lock);
286void      g_static_rw_lock_reader_unlock  (GStaticRWLock* lock);
287void      g_static_rw_lock_writer_lock    (GStaticRWLock* lock);
288gboolean  g_static_rw_lock_writer_trylock (GStaticRWLock* lock);
289void      g_static_rw_lock_writer_unlock  (GStaticRWLock* lock);
290void      g_static_rw_lock_free           (GStaticRWLock* lock);
291
292typedef enum
293{
294  G_ONCE_STATUS_NOTCALLED,
295  G_ONCE_STATUS_PROGRESS,
296  G_ONCE_STATUS_READY 
297} GOnceStatus;
298
299typedef struct _GOnce GOnce;
300struct _GOnce
301{
302  volatile GOnceStatus status;
303  volatile gpointer retval;
304};
305
306#define G_ONCE_INIT { G_ONCE_STATUS_NOTCALLED, NULL }
307
308gpointer g_once_impl (GOnce *once, GThreadFunc func, gpointer arg);
309
310#ifdef G_ATOMIC_OP_MEMORY_BARRIER_NEEDED
311# define g_once(once, func, arg) g_once_impl ((once), (func), (arg))
312#else /* !G_ATOMIC_OP_MEMORY_BARRIER_NEEDED*/
313# define g_once(once, func, arg) \
314  (((once)->status == G_ONCE_STATUS_READY) ? \
315   (once)->retval : \
316   g_once_impl ((once), (func), (arg)))
317#endif /* G_ATOMIC_OP_MEMORY_BARRIER_NEEDED */
318   
319/* these are some convenience macros that expand to nothing if GLib
320 * was configured with --disable-threads. for using StaticMutexes,
321 * you define them with G_LOCK_DEFINE_STATIC (name) or G_LOCK_DEFINE (name)
322 * if you need to export the mutex. With G_LOCK_EXTERN (name) you can
323 * declare such an globally defined lock. name is a unique identifier
324 * for the protected varibale or code portion. locking, testing and
325 * unlocking of such mutexes can be done with G_LOCK(), G_UNLOCK() and
326 * G_TRYLOCK() respectively.
327 */
328extern void glib_dummy_decl (void);
329#define G_LOCK_NAME(name)               g__ ## name ## _lock
330#ifdef  G_THREADS_ENABLED
331#  define G_LOCK_DEFINE_STATIC(name)    static G_LOCK_DEFINE (name)
332#  define G_LOCK_DEFINE(name)           \
333    GStaticMutex G_LOCK_NAME (name) = G_STATIC_MUTEX_INIT
334#  define G_LOCK_EXTERN(name)           extern GStaticMutex G_LOCK_NAME (name)
335
336#  ifdef G_DEBUG_LOCKS
337#    define G_LOCK(name)                G_STMT_START{             \
338        g_log (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG,                   \
339               "file %s: line %d (%s): locking: %s ",             \
340               __FILE__,        __LINE__, G_GNUC_PRETTY_FUNCTION, \
341               #name);                                            \
342        g_static_mutex_lock (&G_LOCK_NAME (name));                \
343     }G_STMT_END
344#    define G_UNLOCK(name)              G_STMT_START{             \
345        g_log (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG,                   \
346               "file %s: line %d (%s): unlocking: %s ",           \
347               __FILE__,        __LINE__, G_GNUC_PRETTY_FUNCTION, \
348               #name);                                            \
349       g_static_mutex_unlock (&G_LOCK_NAME (name));               \
350     }G_STMT_END
351#    define G_TRYLOCK(name)                                       \
352        (g_log (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG,                  \
353               "file %s: line %d (%s): try locking: %s ",         \
354               __FILE__,        __LINE__, G_GNUC_PRETTY_FUNCTION, \
355               #name), g_static_mutex_trylock (&G_LOCK_NAME (name)))
356#  else  /* !G_DEBUG_LOCKS */
357#    define G_LOCK(name) g_static_mutex_lock       (&G_LOCK_NAME (name))
358#    define G_UNLOCK(name) g_static_mutex_unlock   (&G_LOCK_NAME (name))
359#    define G_TRYLOCK(name) g_static_mutex_trylock (&G_LOCK_NAME (name))
360#  endif /* !G_DEBUG_LOCKS */
361#else   /* !G_THREADS_ENABLED */
362#  define G_LOCK_DEFINE_STATIC(name)    extern void glib_dummy_decl (void)
363#  define G_LOCK_DEFINE(name)           extern void glib_dummy_decl (void)
364#  define G_LOCK_EXTERN(name)           extern void glib_dummy_decl (void)
365#  define G_LOCK(name)
366#  define G_UNLOCK(name)
367#  define G_TRYLOCK(name)               (TRUE)
368#endif  /* !G_THREADS_ENABLED */
369
370G_END_DECLS
371
372#endif /* __G_THREAD_H__ */
373
Note: See TracBrowser for help on using the repository browser.