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