Fix crash on startup if an LV2 plugin has a bad .ttl file.
[ardour.git] / libs / glibmm2 / glib / src / thread.hg
1 /* $Id: thread.hg,v 1.13 2005/01/21 12:48:05 murrayc Exp $ */
2
3 /* Copyright (C) 2002 The gtkmm Development Team
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Library 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  * Library General Public License for more details.
14  *
15  * You should have received a copy of the GNU Library General Public
16  * License along with this library; if not, write to the Free
17  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18  */
19
20 _DEFS(glibmm,glib)
21
22 #include <glib.h>
23 #include <cstddef>
24
25 #include <sigc++/sigc++.h>
26 #include <glibmm/error.h>
27 #include <glibmm/timeval.h>
28
29 /* Shadow THREAD_PRIORITY_NORMAL macro (from winbase.h).
30  */
31 #if defined(THREAD_PRIORITY_NORMAL) && !defined(GLIBMM_MACRO_SHADOW_THREAD_PRIORITY_NORMAL)
32 enum { GLIBMM_MACRO_DEFINITION_THREAD_PRIORITY_NORMAL = THREAD_PRIORITY_NORMAL };
33 #undef THREAD_PRIORITY_NORMAL
34 enum { THREAD_PRIORITY_NORMAL = GLIBMM_MACRO_DEFINITION_THREAD_PRIORITY_NORMAL };
35 #define THREAD_PRIORITY_NORMAL THREAD_PRIORITY_NORMAL
36 #define GLIBMM_MACRO_SHADOW_THREAD_PRIORITY_NORMAL 1
37 #endif
38
39
40 /** Initializer macro for Glib::StaticMutex.
41  * @relates Glib::StaticMutex
42  * @hideinitializer
43  */
44 #define GLIBMM_STATIC_MUTEX_INIT { G_STATIC_MUTEX_INIT }
45
46 /** Initializer macro for Glib::StaticRecMutex.
47  * @relates Glib::StaticRecMutex
48  * @hideinitializer
49  */
50 #define GLIBMM_STATIC_REC_MUTEX_INIT { G_STATIC_REC_MUTEX_INIT }
51
52 /** Initializer macro for Glib::StaticRWLock.
53  * @relates Glib::StaticRWLock
54  * @hideinitializer
55  */
56 #define GLIBMM_STATIC_RW_LOCK_INIT { G_STATIC_RW_LOCK_INIT }
57
58 /** Initializer macro for Glib::StaticPrivate.
59  * @relates Glib::StaticPrivate
60  * @hideinitializer
61  */
62 #define GLIBMM_STATIC_PRIVATE_INIT { G_STATIC_PRIVATE_INIT }
63
64
65 namespace Glib
66 {
67
68 /** Specifies the priority of a thread.
69  * @note It is not guaranteed, that threads with different priorities really
70  * behave accordingly. On some systems (e.g. Linux) only <tt>root</tt> can
71  * increase priorities. On other systems (e.g. Solaris) there doesn't seem to
72  * be different scheduling for different priorities. All in all try to avoid
73  * being dependent on priorities.
74  */
75 _WRAP_ENUM(ThreadPriority, GThreadPriority, NO_GTYPE)
76
77 /*! @var ThreadPriority THREAD_PRIORITY_LOW
78  * A priority lower than normal.
79  */
80 /*! @var ThreadPriority THREAD_PRIORITY_NORMAL
81  * The default priority.
82  */
83 /*! @var ThreadPriority THREAD_PRIORITY_HIGH
84  * A priority higher than normal.
85  */
86 /*! @var ThreadPriority THREAD_PRIORITY_URGENT
87  * The highest priority.
88  */
89
90
91 /** @defgroup Threads Threads
92  * Thread abstraction; including threads, different mutexes,
93  * conditions and thread private data.
94  * @{
95  */
96
97 enum NotLock { NOT_LOCK };
98 enum TryLock { TRY_LOCK };
99
100 /** Initializes the GLib thread system.
101  * Before you use a thread related function in glibmm, you should initialize
102  * the thread system.  This is done by calling Glib::thread_init().
103  *
104  * @note You should only call thread_init() with a non-<tt>0</tt> parameter
105  * if you really know what you are doing.
106  *
107  * @note thread_init() must not be called directly or indirectly as
108  * a callback from glibmm.  Also no mutexes may be currently locked while
109  * calling thread_init().
110  *
111  * thread_init() might only be called once.  On the second call it will
112  * abort with an error.  If you want to make sure that the thread system
113  * is initialized, you can do that too:
114  * @code
115  * if(!Glib::thread_supported()) Glib::thread_init();
116  * @endcode
117  * After that line either the thread system is initialized, or the program
118  * will abort if no thread system is available in GLib, i.e. either
119  * @c G_THREADS_ENABLED is not defined or @c G_THREADS_IMPL_NONE is defined.
120  *
121  * If no thread system is available and @a vtable is <tt>0</tt> or if not all
122  * elements of @a vtable are non-<tt>0</tt>, then thread_init() will abort.
123  *
124  * @note To use thread_init() in your program, you have to link with the
125  * libraries that the command <tt>pkg-config&nbsp;--libs&nbsp;gthread-2.0</tt>
126  * outputs.  This is not the case for all the other thread related functions
127  * of glibmm.  Those can be used without having to link with the thread
128  * libraries.  (You @em have to link with <tt>gthread-2.0</tt> if you actually
129  * want to use threads in your application, though.)
130  *
131  * @param vtable A function table of type @c GThreadFunctions, that provides
132  * the entry points to the thread system to be used.
133  */
134 inline void thread_init(GThreadFunctions* vtable = 0);
135
136 /** Returns whether the thread system is initialized.
137  * @return @c true, if the thread system is initialized.
138  */
139 inline bool thread_supported();
140
141
142 class Mutex;
143 class RecMutex;
144 class RWLock;
145 struct StaticMutex;
146 struct StaticRecMutex;
147 struct StaticRWLock;
148
149
150 /** Exception class for thread-related errors.
151  */
152 _WRAP_GERROR(ThreadError, GThreadError, G_THREAD_ERROR, NO_GTYPE)
153
154
155 /** Represents a running thread.
156  * An instance of this class can only be obtained with create(), self(),
157  * or wrap(GThread*).  It's not possible to delete a Thread object.  If the
158  * thread is @em not joinable, its resources will be freed automatically
159  * when it exits.  Otherwise, if the thread @em is joinable, you must call
160  * join() to avoid a memory leak.
161  *
162  * @note g_thread_exit() is not wrapped, because that function exits a thread
163  * without any cleanup.  That's especially dangerous in C++ code, since the
164  * destructors of automatic objects won't be invoked.  Instead, you can throw
165  * a Thread::Exit exception, which will be caught by the internal thread
166  * entry function.
167  *
168  * @note You might have noticed that the thread entry slot doesn't have the
169  * usual void* return value.  If you want to return any data from your thread
170  * you can pass an additional output argument to the thread's entry slot.
171  */
172 class Thread
173 {
174 public:
175   class Exit;
176
177   //See http://bugzilla.gnome.org/show_bug.cgi?id=512348 about the sigc::trackable issue.
178   /** Creates a new thread with the priority <tt>THREAD_PRIORITY_NORMAL</tt>.
179    * If @a joinable is @c true, you can wait for this thread's termination by
180    * calling join().  Otherwise the thread will just disappear, when ready.
181    *
182    * The new thread executes the function or method @a slot points to.  You can
183    * pass additional arguments using sigc::bind().  If the thread was created
184    * successfully, it is returned, otherwise a ThreadError exception is thrown.
185    *
186    * Because sigc::trackable is not thread safe, if the slot represents a
187    * non-static class method (that is, it is created by sigc::mem_fun()), the
188    * class concerned should not derive from sigc::trackable.
189    *
190    * @param slot A slot to execute in the new thread.
191    * @param joinable Should this thread be joinable?
192    * @return The new Thread* on success.
193    * @throw Glib::ThreadError
194    */
195   static Thread* create(const sigc::slot<void>& slot, bool joinable);
196
197   //See http://bugzilla.gnome.org/show_bug.cgi?id=512348 about the sigc::trackable issue.
198   /** Creates a new thread with the priority @a priority. The stack gets the
199    * size @a stack_size or the default value for the current platform, if
200    * @a stack_size is <tt>0</tt>.
201    *
202    * If @a joinable is @c true, you can wait for this thread's termination by
203    * calling join().  Otherwise the thread will just disappear, when ready.
204    * If @a bound is @c true, this thread will be scheduled in the system scope,
205    * otherwise the implementation is free to do scheduling in the process
206    * scope.  The first variant is more expensive resource-wise, but generally
207    * faster.  On some systems (e.g. Linux) all threads are bound.
208    *
209    * The new thread executes the function or method @a slot points to.  You can
210    * pass additional arguments using sigc::bind().  If the thread was created
211    * successfully, it is returned.
212    *
213    * Because sigc::trackable is not thread safe, if the slot represents a
214    * non-static class method (that is, it is created by sigc::mem_fun()), the
215    * class concerned should not derive from sigc::trackable.
216    *
217    * @note It is not guaranteed, that threads with different priorities really
218    * behave accordingly.  On some systems (e.g. Linux) only root can increase
219    * priorities.  On other systems (e.g. Solaris) there doesn't seem to be
220    * different scheduling for different priorities.  All in all try to avoid
221    * being dependent on priorities.  Use <tt>Glib::THREAD_PRIORITY_NORMAL</tt>
222    * here as a default.
223    *
224    * @note Only use the extended
225    * create(const sigc::slot<void>&, unsigned long, bool, bool, ThreadPriority)
226    * function, when you really can't use the simple
227    * create(const sigc::slot<void>&, bool)
228    * instead.  The latter overload does not take @a stack_size, @a bound and
229    * @a priority as arguments, as they should only be used for cases, where
230    * it is inevitable.
231    *
232    * @param slot A slot to execute in the new thread.
233    * @param stack_size A stack size for the new thread, or <tt>0</tt>.
234    * @param joinable Should this thread be joinable?
235    * @param bound Should this thread be bound to a system thread?
236    * @param priority A priority for the thread.
237    * @return The new Thread* on success.
238    * @throw Glib::ThreadError
239    */
240   static Thread* create(const sigc::slot<void>& slot, unsigned long stack_size,
241                         bool joinable, bool bound, ThreadPriority priority);
242
243   /** Returns the Thread* corresponding to the calling thread.
244    * @return The current thread.
245    */
246   static Thread* self();
247
248   /** Returns whether the thread is joinable.
249    * @return Whether the thread is joinable.
250    */
251   bool joinable() const;
252
253   /** Waits until the thread finishes.
254    * Waits until the thread finishes, i.e. the slot, as given to create(),
255    * returns or g_thread_exit() is called by the thread.  (Calling
256    * g_thread_exit() in a C++ program should be avoided.)  All resources of
257    * the thread including the Glib::Thread object are released.  The thread
258    * must have been created with <tt>joinable&nbsp;=&nbsp;true</tt>.
259    */
260   void join();
261
262   /** Changes the priority of the thread to @a priority.
263    * @note It is not guaranteed, that threads with different priorities really
264    * behave accordingly.  On some systems (e.g. Linux) only @c root can
265    * increase priorities.  On other systems (e.g. Solaris) there doesn't seem
266    * to be different scheduling for different priorities.  All in all try to
267    * avoid being dependent on priorities.
268    * @param priority A new priority for the thread.
269    */
270   void set_priority(ThreadPriority priority);
271
272   /** Returns the priority of the thread.
273    * @return The thread's priority.
274    */
275   ThreadPriority get_priority() const;
276
277   /** Gives way to other threads waiting to be scheduled.
278    * This function is often used as a method to make busy wait less evil.  But
279    * in most cases, you will encounter, there are better methods to do that.
280    * So in general you shouldn't use this function.
281    */
282   static void yield();
283
284   GThread*       gobj()       { return &gobject_; }
285   const GThread* gobj() const { return &gobject_; }
286
287 private:
288   GThread gobject_;
289
290   // Glib::Thread can neither be constructed nor deleted.
291   Thread();
292   void operator delete(void*, size_t);
293
294   // noncopyable
295   Thread(const Thread&);
296   Thread& operator=(const Thread&);
297 };
298
299 /** %Exception class used to exit from a thread.
300  * @code
301  * throw Glib::Thread::Exit();
302  * @endcode
303  * Write this if you want to exit from a thread created by Thread::create().
304  * Of course you must make sure not to catch Thread::Exit by accident, i.e.
305  * when using <tt>catch(...)</tt> somewhere in your code.
306  */
307 class Thread::Exit
308 {};
309
310 /** @relates Glib::Thread */
311 Thread* wrap(GThread* gobject);
312
313
314 /** Like Glib::Mutex, but can be defined at compile time.
315  * Use @c GLIBMM_STATIC_MUTEX_INIT to initialize a StaticMutex:
316  * @code
317  * Glib::StaticMutex mutex = GLIBMM_STATIC_MUTEX_INIT;
318  * @endcode
319  * A StaticMutex can be used without calling Glib::thread_init(), it will
320  * silently do nothing then.  That will also work when using the implicit
321  * conversion to Mutex&, thus you can safely use Mutex::Lock with a
322  * StaticMutex.
323  */
324 struct StaticMutex
325 {
326   void lock();
327   bool trylock();
328   void unlock();
329
330   operator Mutex&();
331
332   GStaticMutex* gobj() { return &gobject_; }
333
334 #ifndef DOXYGEN_SHOULD_SKIP_THIS
335   // Must be public to allow initialization at compile time.
336   GStaticMutex gobject_;
337 #endif
338 };
339
340 /** Represents a mutex (mutual exclusion).
341  * It can be used to protect data against shared access.  Try to use
342  * Mutex::Lock instead of calling lock() and unlock() directly&nbsp;--
343  * it will make your life much easier.
344  *
345  * @note Before creating a Glib::Mutex, Glib::thread_init() has to be called.
346  *
347  * @note Glib::Mutex is not recursive, i.e. a thread will deadlock, if it
348  * already has locked the mutex while calling lock().  Use Glib::RecMutex
349  * instead, if you need recursive mutexes.
350  */
351 class Mutex
352 {
353 public:
354   class Lock;
355
356   Mutex();
357   ~Mutex();
358
359   /** Locks the mutex.
360    * If mutex is already locked by another thread, the current thread will
361    * block until mutex is unlocked by the other thread.
362    * @see Mutex::Lock
363    */
364   void lock();
365
366   /** Tries to lock the mutex.
367    * If the mutex is already locked by another thread, it immediately returns
368    * @c false.  Otherwise it locks the mutex and returns @c true.
369    * @return Whether the mutex could be locked.
370    * @see Mutex::Lock
371    */
372   bool trylock();
373
374   /** Unlocks the mutex.
375    * If another thread is blocked in a lock() call for this mutex, it will be
376    * woken and can lock the mutex itself.
377    * @see Mutex::Lock
378    */
379   void unlock();
380
381   GMutex* gobj() { return gobject_; }
382
383 private:
384   GMutex* gobject_;
385
386   // noncopyable
387   Mutex(const Mutex&);
388   Mutex& operator=(const Mutex&);
389 };
390
391 /** Utility class for exception-safe mutex locking.
392  * @par Usage example:
393  * @code
394  * {
395  *   Glib::Mutex::Lock lock (mutex); // calls mutex.lock()
396  *   do_something();
397  * } // the destructor calls mutex.unlock()
398  * @endcode
399  * As you can see, the compiler takes care of the unlocking.  This is not
400  * only exception safe but also much less error-prone.  You could even
401  * <tt>return</tt> while still holding the lock and it will be released
402  * properly.
403  */
404 class Mutex::Lock
405 {
406 public:
407   explicit inline Lock(Mutex& mutex);
408   inline Lock(Mutex& mutex, NotLock);
409   inline Lock(Mutex& mutex, TryLock);
410   inline ~Lock();
411
412   inline void acquire();
413   inline bool try_acquire();
414   inline void release();
415   inline bool locked() const;
416
417 private:
418   Mutex&  mutex_;
419   bool    locked_;
420
421   // noncopyable
422   Lock(const Mutex::Lock&);
423   Mutex::Lock& operator=(const Mutex::Lock&);
424 };
425
426
427 /** Like Glib::RecMutex, but can be defined at compile time.
428  * Use @c GLIBMM_STATIC_REC_MUTEX_INIT to initialize a StaticRecMutex:
429  * @code
430  * Glib::StaticRecMutex mutex = GLIBMM_STATIC_REC_MUTEX_INIT;
431  * @endcode
432  * A StaticRecMutex can be used without calling Glib::thread_init(), it will
433  * silently do nothing then.  That will also work when using the implicit
434  * conversion to RecMutex&, thus you can safely use RecMutex::Lock with a
435  * StaticRecMutex.
436  */
437 struct StaticRecMutex
438 {
439   void lock();
440   bool trylock();
441   void unlock();
442
443   void lock_full(unsigned int depth);
444   unsigned int unlock_full();
445
446   operator RecMutex&();
447
448   GStaticRecMutex* gobj() { return &gobject_; }
449
450 #ifndef DOXYGEN_SHOULD_SKIP_THIS
451   // Must be public to allow initialization at compile time.
452   GStaticRecMutex gobject_;
453 #endif
454 };
455
456 class RecMutex : public StaticRecMutex
457 {
458 public:
459   class Lock;
460
461   RecMutex();
462   ~RecMutex();
463
464 private:
465   // noncopyable
466   RecMutex(const RecMutex&);
467   RecMutex& operator=(const RecMutex&);
468 };
469
470 /** Utility class for exception-safe locking of recursive mutexes.
471  */
472 class RecMutex::Lock
473 {
474 public:
475   explicit inline Lock(RecMutex& mutex);
476   inline Lock(RecMutex& mutex, NotLock);
477   inline Lock(RecMutex& mutex, TryLock);
478   inline ~Lock();
479
480   inline void acquire();
481   inline bool try_acquire();
482   inline void release();
483   inline bool locked() const;
484
485 private:
486   RecMutex& mutex_;
487   bool      locked_;
488
489   // noncopyable
490   Lock(const RecMutex::Lock&);
491   RecMutex::Lock& operator=(const RecMutex::Lock&);
492 };
493
494
495 /** Like Glib::RWLock, but can be defined at compile time.
496  * Use @c GLIBMM_STATIC_RW_LOCK_INIT to initialize a StaticRWLock:
497  * @code
498  * Glib::StaticRWLock rw_lock = GLIBMM_STATIC_RW_LOCK_INIT;
499  * @endcode
500  * A StaticRWLock can be used without calling Glib::thread_init(), it will
501  * silently do nothing then.  That will also work when using the implicit
502  * conversion to RWLock&, thus you can safely use RWLock::ReaderLock and
503  * RWLock::WriterLock with a StaticRWLock.
504  */
505 struct StaticRWLock
506 {
507   void reader_lock();
508   bool reader_trylock();
509   void reader_unlock();
510
511   void writer_lock();
512   bool writer_trylock();
513   void writer_unlock();
514
515   operator RWLock&();
516
517   GStaticRWLock* gobj() { return &gobject_; }
518
519 #ifndef DOXYGEN_SHOULD_SKIP_THIS
520   // Must be public to allow initialization at compile time.
521   GStaticRWLock gobject_;
522 #endif
523 };
524
525 class RWLock : public StaticRWLock
526 {
527 public:
528   class ReaderLock;
529   class WriterLock;
530
531   RWLock();
532   ~RWLock();
533
534 private:
535   // noncopyable
536   RWLock(const RWLock&);
537   RWLock& operator=(const RWLock&);
538 };
539
540 /** Utility class for exception-safe locking of read/write locks.
541  */
542 class RWLock::ReaderLock
543 {
544 public:
545   explicit inline ReaderLock(RWLock& rwlock);
546   inline ReaderLock(RWLock& rwlock, NotLock);
547   inline ReaderLock(RWLock& rwlock, TryLock);
548   inline ~ReaderLock();
549
550   inline void acquire();
551   inline bool try_acquire();
552   inline void release();
553   inline bool locked() const;
554
555 private:
556   RWLock& rwlock_;
557   bool    locked_;
558
559   // noncopyable
560   ReaderLock(const RWLock::ReaderLock&);
561   RWLock::ReaderLock& operator=(const RWLock::ReaderLock&);
562 };
563
564 /** Utility class for exception-safe locking of read/write locks.
565  */
566 class RWLock::WriterLock
567 {
568 public:
569   explicit inline WriterLock(RWLock& rwlock);
570   inline WriterLock(RWLock& rwlock, NotLock);
571   inline WriterLock(RWLock& rwlock, TryLock);
572   inline ~WriterLock();
573
574   inline void acquire();
575   inline bool try_acquire();
576   inline void release();
577   inline bool locked() const;
578
579 private:
580   RWLock& rwlock_;
581   bool    locked_;
582
583   // noncopyable
584   WriterLock(const RWLock::WriterLock&);
585   RWLock::WriterLock& operator=(const RWLock::WriterLock&);
586 };
587
588 /** An opaque data structure to represent a condition. 
589  * A @a Cond is an object that threads can block on, if they find a certain 
590  * condition to be false. If other threads change the state of this condition 
591  * they can signal the @a Cond, such that the waiting thread is woken up.
592  * @par Usage example:
593  * @code
594  * Glib::Cond data_cond;
595  * Glib::Mutex data_mutex;
596  * void* current_data = NULL;
597  * 
598  * void push_data (void* data)
599  * {
600  *   data_mutex.lock();
601  *   current_data = data;
602  *   data_cond.signal();
603  *   data_mutex.unlock();
604  * }
605  * 
606  * void* pop_data ()
607  * {
608  *   void* data;
609  * 
610  *   data_mutex.lock();
611  *   while (!current_data)
612  *       data_cond.wait(data_mutex);
613  *   data = current_data;
614  *   current_data = NULL;
615  *   data_mutex.unlock();
616  *   return data;
617  * }
618  * @endcode
619 */
620 class Cond
621 {
622 public:
623   Cond();
624   ~Cond();
625
626   /** If threads are waiting for this @a Cond, exactly one of them is woken up. 
627    * It is good practice to hold the same lock as the waiting thread, while calling 
628    * this method, though not required.
629    *
630    * @note This method can also be used if @a Glib::thread_init() has not yet been 
631    * called and will do nothing then.
632    */
633   void signal();
634
635   /** If threads are waiting for this @a Cond, all of them are woken up.
636    * It is good practice to hold the same lock as the waiting thread, while calling 
637    * this method, though not required.
638    *
639    * @note This method can also be used if @a Glib::thread_init() has not yet been 
640    * called and will do nothing then.
641    */
642   void broadcast();
643
644   /** Waits until this thread is woken up on this @a Cond.
645    * The mutex is unlocked before falling asleep and locked again before resuming.
646    *
647    * This method can also be used if @a Glib::thread_init() has not yet been 
648    * called and will immediately return then. 
649    *
650    * @param mutex a @a Mutex that is currently locked.
651    * 
652    * @note It is important to use the @a wait() and @a timed_wait() methods
653    * only inside a loop, which checks for the condition to be true as it is not 
654    * guaranteed that the waiting thread will find it fulfilled, even if the signaling 
655    * thread left the condition in that state. This is because another thread can have 
656    * altered the condition, before the waiting thread got the chance to be woken up, 
657    * even if the condition itself is protected by a @a Mutex.
658    */
659   void wait(Mutex& mutex);
660
661   /** Waits until this thread is woken up on this @a Cond, but not longer than until the time, that is specified by @a abs_time.
662    * The mutex is unlocked before falling asleep and locked again before resuming.
663    *
664    * This function can also be used, if @a Glib::thread_init() has not yet been 
665    * called and will immediately return @c true then. 
666    *
667    * @param mutex a @a Mutex that is currently locked.
668    * @param abs_time a max time to wait.
669    * 
670    * @note It is important to use the @a wait() and @a timed_wait() methods
671    * only inside a loop, which checks for the condition to be true as it is not 
672    * guaranteed that the waiting thread will find it fulfilled, even if the signaling 
673    * thread left the condition in that state. This is because another thread can have 
674    * altered the condition, before the waiting thread got the chance to be woken up, 
675    * even if the condition itself is protected by a @a Mutex.
676    */
677   bool timed_wait(Mutex& mutex, const Glib::TimeVal& abs_time);
678
679   GCond* gobj() { return gobject_; }
680
681 private:
682   GCond* gobject_;
683
684   // noncopyable
685   Cond(const Cond&);
686   Cond& operator=(const Cond&);
687 };
688
689
690 template <class T>
691 struct StaticPrivate
692 {
693   typedef void (*DestroyNotifyFunc) (void*);
694
695   static void delete_ptr(void* data);
696
697   inline T* get();
698   inline void set(T* data, DestroyNotifyFunc notify_func = &StaticPrivate<T>::delete_ptr);
699
700   GStaticPrivate* gobj() { return &gobject_; }
701
702 #ifndef DOXYGEN_SHOULD_SKIP_THIS
703   // Must be public to allow initialization at compile time.
704   GStaticPrivate gobject_;
705 #endif
706 };
707
708 template <class T>
709 class Private
710 {
711 public:
712   typedef void (*DestructorFunc) (void*);
713
714   static void delete_ptr(void* data);
715
716   explicit inline Private(DestructorFunc destructor_func = &Private<T>::delete_ptr);
717   inline T* get();
718   inline void set(T* data);
719
720   GPrivate* gobj() { return gobject_; }
721
722 private:
723   GPrivate* gobject_;
724
725   // noncopyable
726   Private(const Private<T>&);
727   Private<T>& operator=(const Private<T>&);
728 };
729
730 /** @} group Threads */
731
732 /*! A glibmm thread example.
733  * @example thread/thread.cc
734  */
735
736
737 #ifndef DOXYGEN_SHOULD_SKIP_THIS
738
739 /***************************************************************************/
740 /*  inline implementation                                                  */
741 /***************************************************************************/
742
743 // internal
744 void thread_init_impl();
745
746 /* This function must be inline, to avoid an unnecessary dependency on
747  * libgthread even if the thread system is not used.  libgthread might
748  * not even be available if GLib was compiled without thread support.
749  */
750 inline
751 void thread_init(GThreadFunctions* vtable)
752 {
753   g_thread_init(vtable);
754   Glib::thread_init_impl();
755 }
756
757 inline
758 bool thread_supported()
759 {
760   //MSVC++ needs the != 0 to avoid an int -> bool cast warning.
761   return (g_thread_supported() != 0);
762 }
763
764
765 /**** Glib::Mutex::Lock ****************************************************/
766
767 inline
768 Mutex::Lock::Lock(Mutex& mutex)
769 :
770   mutex_  (mutex),
771   locked_ (true)
772 {
773   mutex_.lock();
774 }
775
776 inline
777 Mutex::Lock::Lock(Mutex& mutex, NotLock)
778 :
779   mutex_  (mutex),
780   locked_ (false)
781 {}
782
783 inline
784 Mutex::Lock::Lock(Mutex& mutex, TryLock)
785 :
786   mutex_  (mutex),
787   locked_ (mutex.trylock())
788 {}
789
790 inline
791 Mutex::Lock::~Lock()
792 {
793   if(locked_)
794     mutex_.unlock();
795 }
796
797 inline
798 void Mutex::Lock::acquire()
799 {
800   mutex_.lock();
801   locked_ = true;
802 }
803
804 inline
805 bool Mutex::Lock::try_acquire()
806 {
807   locked_ = mutex_.trylock();
808   return locked_;
809 }
810
811 inline
812 void Mutex::Lock::release()
813 {
814   mutex_.unlock();
815   locked_ = false;
816 }
817
818 inline
819 bool Mutex::Lock::locked() const
820 {
821   return locked_;
822 }
823
824
825 /**** Glib::RecMutex::Lock *************************************************/
826
827 inline
828 RecMutex::Lock::Lock(RecMutex& mutex)
829 :
830   mutex_  (mutex),
831   locked_ (true)
832 {
833   mutex_.lock();
834 }
835
836 inline
837 RecMutex::Lock::Lock(RecMutex& mutex, NotLock)
838 :
839   mutex_  (mutex),
840   locked_ (false)
841 {}
842
843 inline
844 RecMutex::Lock::Lock(RecMutex& mutex, TryLock)
845 :
846   mutex_  (mutex),
847   locked_ (mutex.trylock())
848 {}
849
850 inline
851 RecMutex::Lock::~Lock()
852 {
853   if(locked_)
854     mutex_.unlock();
855 }
856
857 inline
858 void RecMutex::Lock::acquire()
859 {
860   mutex_.lock();
861   locked_ = true;
862 }
863
864 inline
865 bool RecMutex::Lock::try_acquire()
866 {
867   locked_ = mutex_.trylock();
868   return locked_;
869 }
870
871 inline
872 void RecMutex::Lock::release()
873 {
874   mutex_.unlock();
875   locked_ = false;
876 }
877
878 inline
879 bool RecMutex::Lock::locked() const
880 {
881   return locked_;
882 }
883
884
885 /**** Glib::RWLock::ReaderLock *********************************************/
886
887 inline
888 RWLock::ReaderLock::ReaderLock(RWLock& rwlock)
889 :
890   rwlock_ (rwlock),
891   locked_ (true)
892 {
893   rwlock_.reader_lock();
894 }
895
896 inline
897 RWLock::ReaderLock::ReaderLock(RWLock& rwlock, NotLock)
898 :
899   rwlock_ (rwlock),
900   locked_ (false)
901 {}
902
903 inline
904 RWLock::ReaderLock::ReaderLock(RWLock& rwlock, TryLock)
905 :
906   rwlock_ (rwlock),
907   locked_ (rwlock.reader_trylock())
908 {}
909
910 inline
911 RWLock::ReaderLock::~ReaderLock()
912 {
913   if(locked_)
914     rwlock_.reader_unlock();
915 }
916
917 inline
918 void RWLock::ReaderLock::acquire()
919 {
920   rwlock_.reader_lock();
921   locked_ = true;
922 }
923
924 inline
925 bool RWLock::ReaderLock::try_acquire()
926 {
927   locked_ = rwlock_.reader_trylock();
928   return locked_;
929 }
930
931 inline
932 void RWLock::ReaderLock::release()
933 {
934   rwlock_.reader_unlock();
935   locked_ = false;
936 }
937
938 inline
939 bool RWLock::ReaderLock::locked() const
940 {
941   return locked_;
942 }
943
944
945 /**** Glib::RWLock::WriterLock *********************************************/
946
947 inline
948 RWLock::WriterLock::WriterLock(RWLock& rwlock)
949 :
950   rwlock_ (rwlock),
951   locked_ (true)
952 {
953   rwlock_.writer_lock();
954 }
955
956 inline
957 RWLock::WriterLock::WriterLock(RWLock& rwlock, NotLock)
958 :
959   rwlock_ (rwlock),
960   locked_ (false)
961 {}
962
963 inline
964 RWLock::WriterLock::WriterLock(RWLock& rwlock, TryLock)
965 :
966   rwlock_ (rwlock),
967   locked_ (rwlock.writer_trylock())
968 {}
969
970 inline
971 RWLock::WriterLock::~WriterLock()
972 {
973   if(locked_)
974     rwlock_.writer_unlock();
975 }
976
977 inline
978 void RWLock::WriterLock::acquire()
979 {
980   rwlock_.writer_lock();
981   locked_ = true;
982 }
983
984 inline
985 bool RWLock::WriterLock::try_acquire()
986 {
987   locked_ = rwlock_.writer_trylock();
988   return locked_;
989 }
990
991 inline
992 void RWLock::WriterLock::release()
993 {
994   rwlock_.writer_unlock();
995   locked_ = false;
996 }
997
998 inline
999 bool RWLock::WriterLock::locked() const
1000 {
1001   return locked_;
1002 }
1003
1004
1005 /**** Glib::StaticPrivate **************************************************/
1006
1007 // static
1008 template <class T>
1009 void StaticPrivate<T>::delete_ptr(void* data)
1010 {
1011   delete static_cast<T*>(data);
1012 }
1013
1014 template <class T> inline
1015 T* StaticPrivate<T>::get()
1016 {
1017   return static_cast<T*>(g_static_private_get(&gobject_));
1018 }
1019
1020 template <class T> inline
1021 void StaticPrivate<T>::set(T* data, typename StaticPrivate<T>::DestroyNotifyFunc notify_func)
1022 {
1023   g_static_private_set(&gobject_, data, notify_func);
1024 }
1025
1026
1027 /**** Glib::Private ********************************************************/
1028
1029 // static
1030 template <class T>
1031 void Private<T>::delete_ptr(void* data)
1032 {
1033   delete static_cast<T*>(data);
1034 }
1035
1036 template <class T> inline
1037 Private<T>::Private(typename Private<T>::DestructorFunc destructor_func)
1038 :
1039   gobject_ (g_private_new(destructor_func))
1040 {}
1041
1042 template <class T> inline
1043 T* Private<T>::get()
1044 {
1045   return static_cast<T*>(g_private_get(gobject_));
1046 }
1047
1048 template <class T> inline
1049 void Private<T>::set(T* data)
1050 {
1051   g_private_set(gobject_, data);
1052 }
1053
1054 #endif /* DOXYGEN_SHOULD_SKIP_THIS */
1055
1056 } // namespace Glib
1057