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