1 // Generated by gmmproc 2.64.2 -- DO NOT MODIFY!
2 #ifndef _GLIBMM_THREADS_H
3 #define _GLIBMM_THREADS_H
4 
5 #include <glibmmconfig.h>
6 
7 #ifndef GLIBMM_DISABLE_DEPRECATED
8 
9 
10 /* Copyright (C) 2002 The gtkmm Development Team
11  *
12  * This library is free software; you can redistribute it and/or
13  * modify it under the terms of the GNU Lesser General Public
14  * License as published by the Free Software Foundation; either
15  * version 2.1 of the License, or (at your option) any later version.
16  *
17  * This library is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
20  * Lesser General Public License for more details.
21  *
22  * You should have received a copy of the GNU Lesser General Public
23  * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
24  */
25 
26 
27  // This whole file is deprecated.
28 
29 
30 #include <glib.h>
31 #include <glibmm/error.h>
32 #include <sigc++/sigc++.h>
33 #include <string>
34 #include <cstddef>
35 
36 namespace Glib
37 {
38 
39 /**
40  * @deprecated The entire Glib::Threads API is deprecated in favor of the
41  * standard C++ concurrency API in C++11 and C++14.
42  */
43 namespace Threads
44 {
45 //The GMMPROC_EXTRA_NAMESPACE() macro is a hint to generate_wrap_init.pl to put it in the Threads sub-namespace
46 
47 
48 /** @defgroup Threads Threads
49  * %Thread abstraction; including threads, different mutexes,
50  * conditions and thread private data.
51  *
52  * @deprecated The entire Glib::Threads API is deprecated in favor of the
53  * standard C++ concurrency API in C++11 and C++14.
54  * @{
55  */
56 
57 /// @deprecated Please use std::lock_guard or std::unique_lock instead.
58 enum NotLock { NOT_LOCK };
59 
60 /// @deprecated Please use std::lock_guard or std::unique_lock instead.
61 enum TryLock { TRY_LOCK };
62 
63 class GLIBMM_API Mutex;
64 class GLIBMM_API RecMutex;
65 class GLIBMM_API RWLock;
66 
67 /**  %Exception class for thread-related errors.
68  *
69  * @deprecated Please use std::lock_guard or std::unique_lock instead.
70  */
71 class GLIBMM_API ThreadError : public Glib::Error
72 {
73 public:
74   /**  @var Code AGAIN
75    * A thread couldn't be created due to resource
76    * shortage. Try again later.
77    *
78    *  @enum Code
79    *
80    * Possible errors of thread related functions.
81    */
82   enum Code
83   {
84     AGAIN
85   };
86 
87   ThreadError(Code error_code, const Glib::ustring& error_message);
88   explicit ThreadError(GError* gobject);
89   Code code() const;
90 
91 #ifndef DOXYGEN_SHOULD_SKIP_THIS
92 private:
93 
94   static void throw_func(GError* gobject);
95 
96   friend GLIBMM_API void wrap_init(); // uses throw_func()
97 
98   #endif //DOXYGEN_SHOULD_SKIP_THIS
99 };
100 
101 
102 /** Represents a running thread.
103  * An instance of this class can only be obtained with create(), self(),
104  * or wrap(GThread*).  It's not possible to delete a Thread object.
105  * You must call join() to avoid a memory leak.
106  *
107  * @note g_thread_exit() is not wrapped, because that function exits a thread
108  * without any cleanup.  That's especially dangerous in C++ code, since the
109  * destructors of automatic objects won't be invoked.  Instead, you can throw
110  * a Threads::Thread::Exit exception, which will be caught by the internal thread
111  * entry function.
112  *
113  * @note The thread entry slot doesn't have the void* return value that a
114  * GThreadFunc has.  If you want to return any data from your thread,
115  * you can pass an additional output argument to the thread's entry slot.
116  *
117  * @deprecated Please use std::thread instead.
118  */
119 class GLIBMM_API Thread
120 {
121 public:
122 
123   Thread(const Thread&) = delete;
124   Thread& operator=(const Thread&) = delete;
125 
126   class Exit;
127 
128   //See http://bugzilla.gnome.org/show_bug.cgi?id=512348 about the sigc::trackable issue.
129   // TODO: At the next ABI break, consider changing const sigc::slot<void>& slot
130   // to const std::function<void()>& func, if it can be assumed that all supported
131   // compilers understand the C++11 template class std::function<>.
132   /** Creates a new thread.
133    * You can wait for this thread's termination by calling join().
134    *
135    * The new thread executes the function or method @a slot points to.  You can
136    * pass additional arguments using sigc::bind().  If the thread was created
137    * successfully, it is returned, otherwise a Threads::ThreadError exception is thrown.
138    *
139    * Because sigc::trackable is not thread-safe, if the slot represents a
140    * non-static class method and is created by sigc::mem_fun(), the class concerned
141    * should not derive from sigc::trackable. You can use, say, boost::bind() or,
142    * in C++11, std::bind() or a C++11 lambda expression instead of sigc::mem_fun().
143    *
144    * @param slot A slot to execute in the new thread.
145    * @return The new Thread* on success.
146    * @throw Glib::Threads::ThreadError
147    */
148   static Thread* create(const sigc::slot<void>& slot);
149 
150   // TODO: At next ABI break, remove the single parameter create
151   //       method and default name to std::string()
152 
153   /** Creates a new named thread.
154    * You can wait for this thread's termination by calling join().
155    *
156    * The new thread executes the function or method @a slot points to.  You can
157    * pass additional arguments using sigc::bind().  If the thread was created
158    * successfully, it is returned, otherwise a Threads::ThreadError exception is thrown.
159    *
160    * Because sigc::trackable is not thread-safe, if the slot represents a
161    * non-static class method and is created by sigc::mem_fun(), the class concerned
162    * should not derive from sigc::trackable. You can use, say, boost::bind() or,
163    * in C++11, std::bind() or a C++11 lambda expression instead of sigc::mem_fun().
164    *
165    * The @a name can be useful for discriminating threads in a debugger.
166    * It is not used for other purposes and does not have to be unique.
167    * Some systems restrict the length of @a name to 16 bytes.
168    *
169    * @param slot A slot to execute in the new thread.
170    * @param name A name for the new thread.
171    * @return The new Thread* on success.
172    * @throw Glib::Threads::ThreadError
173    *
174    * @newin{2,36}
175    */
176   static Thread* create(const sigc::slot<void>& slot, const std::string& name);
177 
178   /** Returns the Thread* corresponding to the calling thread.
179    * @return The current thread.
180    */
181   static Thread* self();
182 
183   /** Waits until the thread finishes.
184    * Waits until the thread finishes, i.e. the slot, as given to create(),
185    * returns or g_thread_exit() is called by the thread.  (Calling
186    * g_thread_exit() in a C++ program should be avoided.)  All resources of
187    * the thread including the Glib::Threads::Thread object are released.
188    */
189   void join();
190 
191   /** Gives way to other threads waiting to be scheduled.
192    * This function is often used as a method to make busy wait less evil.  But
193    * in most cases, you will encounter, there are better methods to do that.
194    * So in general you shouldn't use this function.
195    */
196   static void yield();
197 
198   GThread*       gobj();
199   const GThread* gobj() const;
200 
201 private:
202   // Glib::Thread can neither be constructed nor deleted.
203   Thread();
204   void operator delete(void*, std::size_t);
205 };
206 
207 /** %Exception class used to exit from a thread.
208  * @code
209  * throw Glib::Threads::Thread::Exit();
210  * @endcode
211  * Write this if you want to exit from a thread created by Threads::Thread::create().
212  * Of course you must make sure not to catch Threads::Thread::Exit by accident, i.e.
213  * when using <tt>catch(...)</tt> somewhere in your code.
214  *
215  * @deprecated Please use std::thread instead.
216  */
217 class GLIBMM_API Thread::Exit
218 {};
219 
220 /** A C++ wrapper for the C object.
221  *
222  * @param gobject The C instance.
223  * @return The C++ wrapper.
224  *
225  * @relates Glib::Threads::Thread
226  *
227  * @deprecated Please use std::thread instead.
228  */
229 Thread* wrap(GThread* gobject);
230 
231 /** Represents a mutex (mutual exclusion).
232  * It can be used to protect data against shared access.  Try to use
233  * Mutex::Lock instead of calling lock() and unlock() directly&nbsp;--
234  * it will make your life much easier.
235  *
236  * @note Glib::Threads::Mutex is not recursive, i.e. a thread will deadlock, if it
237  * already has locked the mutex while calling lock().  Use Glib::Threads::RecMutex
238  * instead, if you need recursive mutexes.
239  *
240  * @deprecated Please use std::mutex instead.
241  */
242 class GLIBMM_API Mutex
243 {
244 public:
245   class Lock;
246 
247   Mutex();
248 
249   Mutex(const Mutex&) = delete;
250   Mutex& operator=(const Mutex&) = delete;
251 
252   ~Mutex();
253 
254   /** Locks the mutex.
255    * If mutex is already locked by another thread, the current thread will
256    * block until mutex is unlocked by the other thread.
257    * @see Mutex::Lock
258    */
259   void lock();
260 
261   /** Tries to lock the mutex.
262    * If the mutex is already locked by another thread, it immediately returns
263    * @c false.  Otherwise it locks the mutex and returns @c true.
264    * @return Whether the mutex could be locked.
265    * @see Mutex::Lock
266    */
267   bool trylock();
268 
269   /** Unlocks the mutex.
270    * If another thread is blocked in a lock() call for this mutex, it will be
271    * woken and can lock the mutex itself.
272    * @see Mutex::Lock
273    */
274   void unlock();
275 
gobj()276   GMutex* gobj() { return &gobject_; }
277 
278 private:
279   GMutex gobject_;
280 };
281 
282 /** Utility class for exception-safe mutex locking.
283  * @par Usage example:
284  * @code
285  * {
286  *   Glib::Threads::Mutex::Lock lock(mutex); // calls mutex.lock()
287  *   do_something();
288  * } // the destructor calls mutex.unlock()
289  * @endcode
290  * As you can see, the compiler takes care of the unlocking.  This is not
291  * only exception-safe but also much less error-prone.  You could even
292  * <tt>return</tt> while still holding the lock and it will be released
293  * properly.
294  *
295  * @deprecated Please use std::lock_guard or std::unique_lock instead.
296  */
297 class GLIBMM_API Mutex::Lock
298 {
299 public:
300   explicit inline Lock(Mutex& mutex);
301   inline Lock(Mutex& mutex, NotLock);
302   inline Lock(Mutex& mutex, TryLock);
303 
304   Lock(const Mutex::Lock&) = delete;
305   Mutex::Lock& operator=(const Mutex::Lock&) = delete;
306 
307   inline ~Lock();
308 
309   inline void acquire();
310   inline bool try_acquire();
311   inline void release();
312   inline bool locked() const;
313 
314 private:
315   Mutex&  mutex_;
316   bool    locked_;
317 };
318 
319 /** A C++ wrapper for the C object.
320  * Do not use operator delete on the returned pointer. If the caller owns the
321  * GMutex object, the caller must destroy it in the same way as if this function
322  * had not been called.
323  *
324  * @param gobject The C instance.
325  * @result The GMutex* cast to a Glib::Threads::Mutex*.
326  *
327  * @relates Glib::Threads::Mutex
328  */
329 Mutex* wrap(GMutex* gobject);
330 
331 /** This represents a recursive mutex.
332  * It is similar to a Mutex with the difference
333  * that it is possible to lock a RecMutex multiple times in the same
334  * thread without deadlock. When doing so, care has to be taken to
335  * unlock the recursive mutex as often as it has been locked.
336  *
337  * @deprecated Please use std::recursive_mutex instead.
338  */
339 class GLIBMM_API RecMutex
340 {
341 public:
342   class Lock;
343 
344   RecMutex();
345 
346   RecMutex(const RecMutex&) = delete;
347   RecMutex& operator=(const RecMutex&) = delete;
348 
349   ~RecMutex();
350 
351   void lock();
352   bool trylock();
353   void unlock();
354 
gobj()355   GRecMutex* gobj() { return &gobject_; }
356 
357 private:
358   GRecMutex gobject_;
359 };
360 
361 /** Utility class for exception-safe locking of recursive mutexes.
362  *
363  * @deprecated Please use std::lock_guard or std::unique_lock instead.
364  */
365 class GLIBMM_API RecMutex::Lock
366 {
367 public:
368   explicit inline Lock(RecMutex& mutex);
369   inline Lock(RecMutex& mutex, NotLock);
370   inline Lock(RecMutex& mutex, TryLock);
371 
372   Lock(const RecMutex::Lock&) = delete;
373   RecMutex::Lock& operator=(const RecMutex::Lock&) = delete;
374 
375   inline ~Lock();
376 
377   inline void acquire();
378   inline bool try_acquire();
379   inline void release();
380   inline bool locked() const;
381 
382 private:
383   RecMutex& mutex_;
384   bool      locked_;
385 };
386 
387 /** A C++ wrapper for the C object.
388  * Do not use operator delete on the returned pointer. If the caller owns the
389  * GRecMutex object, the caller must destroy it in the same way as if this function
390  * had not been called.
391  *
392  * @param gobject The C instance.
393  * @result The GRecMutex* cast to a Glib::Threads::RecMutex*.
394  *
395  * @relates Glib::Threads::RecMutex
396  */
397 RecMutex* wrap(GRecMutex* gobject);
398 
399 /** This represents a reader-writer lock.
400  * It is similar to a Mutex in that it allows
401  * multiple threads to coordinate access to a shared resource.
402  *
403  * The difference to a mutex is that a reader-writer lock discriminates
404  * between read-only ('reader') and full ('writer') access. While only
405  * one thread at a time is allowed write access (by holding the 'writer'
406  * lock via writer_lock()), multiple threads can gain
407  * simultaneous read-only access (by holding the 'reader' lock via
408  * reader_lock()).
409  *
410  * @deprecated Please use std::lock_guard or std::unique_lock instead, with std::shared_timed_mutex.
411  */
412 class GLIBMM_API RWLock
413 {
414 public:
415   class ReaderLock;
416   class WriterLock;
417 
418   RWLock();
419 
420   RWLock(const RWLock&) = delete;
421   RWLock& operator=(const RWLock&) = delete;
422 
423   ~RWLock();
424 
425   void reader_lock();
426   bool reader_trylock();
427   void reader_unlock();
428 
429   void writer_lock();
430   bool writer_trylock();
431   void writer_unlock();
432 
gobj()433   GRWLock* gobj() { return &gobject_; }
434 
435 private:
436   GRWLock gobject_;
437 };
438 
439 /** Utility class for exception-safe locking of read/write locks.
440  *
441  * @deprecated Please use std::lock_guard or std::unique_lock instead, with std::shared_timed_mutex.
442  */
443 class GLIBMM_API RWLock::ReaderLock
444 {
445 public:
446   explicit inline ReaderLock(RWLock& rwlock);
447   inline ReaderLock(RWLock& rwlock, NotLock);
448   inline ReaderLock(RWLock& rwlock, TryLock);
449 
450   ReaderLock(const RWLock::ReaderLock&) = delete;
451   RWLock::ReaderLock& operator=(const RWLock::ReaderLock&) = delete;
452 
453   inline ~ReaderLock();
454 
455   inline void acquire();
456   inline bool try_acquire();
457   inline void release();
458   inline bool locked() const;
459 
460 private:
461   RWLock& rwlock_;
462   bool    locked_;
463 };
464 
465 /** Utility class for exception-safe locking of read/write locks.
466  *
467  * @deprecated Please use std::lock_guard or std::unique_lock instead, with std::shared_timed_mutex.
468  */
469 class GLIBMM_API RWLock::WriterLock
470 {
471 public:
472   explicit inline WriterLock(RWLock& rwlock);
473   inline WriterLock(RWLock& rwlock, NotLock);
474   inline WriterLock(RWLock& rwlock, TryLock);
475 
476   WriterLock(const RWLock::WriterLock&) = delete;
477   RWLock::WriterLock& operator=(const RWLock::WriterLock&) = delete;
478 
479   inline ~WriterLock();
480 
481   inline void acquire();
482   inline bool try_acquire();
483   inline void release();
484   inline bool locked() const;
485 
486 private:
487   RWLock& rwlock_;
488   bool    locked_;
489 };
490 
491 /** An opaque data structure to represent a condition.
492  * A @a Cond is an object that threads can block on, if they find a certain
493  * condition to be false. If other threads change the state of this condition
494  * they can signal the @a Cond, such that the waiting thread is woken up.
495  *
496  * @deprecated Please use std::condition_variable instead.
497  *
498  * @par Usage example:
499  * @code
500  * Glib::Threads::Cond  data_cond;
501  * Glib::Threads::Mutex data_mutex;
502  * void* current_data = nullptr;
503  *
504  * void push_data(void* data)
505  * {
506  *   Glib::Threads::Mutex::Lock lock(data_mutex);
507  *
508  *   current_data = data;
509  *   data_cond.signal();
510  * }
511  *
512  * void* pop_data()
513  * {
514  *   Glib::Threads::Mutex::Lock lock(data_mutex);
515  *
516  *   while (!current_data)
517  *     data_cond.wait(data_mutex);
518  *
519  *   void* const data = current_data;
520  *   current_data = nullptr;
521  *
522  *   return data;
523  * }
524  * @endcode
525  */
526 class GLIBMM_API Cond
527 {
528 public:
529   Cond();
530 
531   Cond(const Cond&) = delete;
532   Cond& operator=(const Cond&) = delete;
533 
534   ~Cond();
535 
536   /** If threads are waiting for this @a Cond, exactly one of them is woken up.
537    * It is good practice to hold the same lock as the waiting thread, while calling
538    * this method, though not required.
539    */
540   void signal();
541 
542   /** If threads are waiting for this @a Cond, all of them are woken up.
543    * It is good practice to hold the same lock as the waiting threads, while calling
544    * this method, though not required.
545    */
546   void broadcast();
547 
548   /** Waits until this thread is woken up on this @a Cond.
549    * The mutex is unlocked before falling asleep and locked again before resuming.
550    *
551    * @param mutex A @a Mutex that is currently locked.
552    *
553    * @note It is important to use the @a wait() and @a wait_until() methods
554    * only inside a loop, which checks for the condition to be true as it is not
555    * guaranteed that the waiting thread will find it fulfilled, even if the signaling
556    * thread left the condition in that state. This is because another thread can have
557    * altered the condition, before the waiting thread got the chance to be woken up,
558    * even if the condition itself is protected by a @a Mutex.
559    */
560   void wait(Mutex& mutex);
561 
562   /** Waits until this thread is woken up on this @a Cond, but not longer
563    * than until the time specified by @a end_time.
564    * The mutex is unlocked before falling asleep and locked again before resuming.
565    *
566    * @par Usage example:
567    * Extending the example presented in the documentation of class Cond.
568    * @code
569    * void* pop_data_timed()
570    * {
571    *   Glib::Threads::Mutex::Lock lock(data_mutex);
572    *
573    *   // Wait at most 5 seconds.
574    *   const gint64 end_time = g_get_monotonic_time() + 5 * G_TIME_SPAN_SECOND;
575    *   while (!current_data)
576    *     if (!data_cond.wait_until(data_mutex, end_time)
577    *       return nullptr; // timeout
578    *
579    *   void* const data = current_data;
580    *   current_data = nullptr;
581    *
582    *   return data;
583    * }
584    * @endcode
585    * The end time is calculated once, before entering the loop, and reused.
586    * This is the motivation behind the use of absolute time. If a relative time
587    * of 5 seconds were passed directly to the call and a spurious wakeup
588    * occurred, the program would have to start over waiting again, which would
589    * lead to a total wait time of more than 5 seconds.
590    *
591    * @param mutex A @a Mutex that is currently locked.
592    * @param end_time The monotonic time to wait until, in microseconds.
593    *                 See g_get_monotonic_time().
594    * @return <tt>true</tt> if the condition variable was signalled (or in the case
595    *         of a spurious wakeup), <tt>false</tt> if @a end_time has passed.
596    *
597    * @note It is important to use the @a wait() and @a wait_until() methods
598    * only inside a loop, which checks for the condition to be true as it is not
599    * guaranteed that the waiting thread will find it fulfilled, even if the signaling
600    * thread left the condition in that state. This is because another thread can have
601    * altered the condition, before the waiting thread got the chance to be woken up,
602    * even if the condition itself is protected by a @a Mutex.
603    */
604   bool wait_until(Mutex& mutex, gint64 end_time);
605 
gobj()606   GCond* gobj() { return &gobject_; }
607 
608 private:
609   GCond gobject_;
610 };
611 
612 /** Thread-local data pointer.
613  *
614  * It is recommended that all instances of this class are statically allocated.
615  * The first time an instance is used (get(), set() or replace() is called)
616  * glib allocates a scarce OS resource that cannot be deallocated.
617  *
618  * @deprecated Please use the thread_local keyword instead.
619  */
620 template <class T>
621 class Private
622 {
623 public:
624   Private(const Private<T>&) = delete;
625   Private<T>& operator=(const Private<T>&) = delete;
626 
627   using DestructorFunc = void (*) (void*);
628 
629   /** Deletes static_cast<T*>(data)
630    */
631   static void delete_ptr(void* data);
632 
633   /** Constructor.
634    *
635    * @param destructor_func Function pointer, or <tt>nullptr</tt>. If @a destructor_func is not <tt>nullptr</tt>
636    * and the stored data pointer is not <tt>nullptr</tt>, this function is called when replace()
637    * is called and when the thread exits.
638    */
639   explicit inline Private(DestructorFunc destructor_func = &Private<T>::delete_ptr);
640 
641   /** Gets the pointer stored in the calling thread.
642    *
643    * @return If no value has yet been set in this thread, <tt>nullptr</tt> is returned.
644    */
645   inline T* get();
646 
647   /** Sets the pointer in the calling thread without calling <tt>destructor_func()</tt>.
648    */
649   inline void set(T* data);
650 
651   /** Sets the pointer in the calling thread and calls <tt>destructor_func()</tt>.
652    * If a function pointer (and not <tt>nullptr</tt>) was specified in the constructor, and
653    * the stored data pointer before the call to replace() is not <tt>nullptr</tt>, then
654    * <tt>destructor_func()</tt> is called with this old pointer value.
655    *
656    * @newin{2,32}
657    */
658   inline void replace(T* data);
659 
gobj()660   GPrivate* gobj() { return &gobject_; }
661 
662 private:
663   GPrivate gobject_;
664 };
665 
666 /** @} group Threads */
667 
668 /*! A glibmm thread example.
669  * @example thread/thread.cc
670  */
671 
672 
673 #ifndef DOXYGEN_SHOULD_SKIP_THIS
674 
675 /***************************************************************************/
676 /*  inline implementation                                                  */
677 /***************************************************************************/
678 
679 /**** Glib::Threads::Mutex::Lock *******************************************/
680 
681 inline
Lock(Mutex & mutex)682 Mutex::Lock::Lock(Mutex& mutex)
683 :
684   mutex_  (mutex),
685   locked_ (true)
686 {
687   mutex_.lock();
688 }
689 
690 inline
Lock(Mutex & mutex,NotLock)691 Mutex::Lock::Lock(Mutex& mutex, NotLock)
692 :
693   mutex_  (mutex),
694   locked_ (false)
695 {}
696 
697 inline
Lock(Mutex & mutex,TryLock)698 Mutex::Lock::Lock(Mutex& mutex, TryLock)
699 :
700   mutex_  (mutex),
701   locked_ (mutex.trylock())
702 {}
703 
704 inline
~Lock()705 Mutex::Lock::~Lock()
706 {
707   if(locked_)
708     mutex_.unlock();
709 }
710 
711 inline
acquire()712 void Mutex::Lock::acquire()
713 {
714   mutex_.lock();
715   locked_ = true;
716 }
717 
718 inline
try_acquire()719 bool Mutex::Lock::try_acquire()
720 {
721   locked_ = mutex_.trylock();
722   return locked_;
723 }
724 
725 inline
release()726 void Mutex::Lock::release()
727 {
728   mutex_.unlock();
729   locked_ = false;
730 }
731 
732 inline
locked()733 bool Mutex::Lock::locked() const
734 {
735   return locked_;
736 }
737 
738 
739 /**** Glib::Threads::RecMutex::Lock ****************************************/
740 
741 inline
Lock(RecMutex & mutex)742 RecMutex::Lock::Lock(RecMutex& mutex)
743 :
744   mutex_  (mutex),
745   locked_ (true)
746 {
747   mutex_.lock();
748 }
749 
750 inline
Lock(RecMutex & mutex,NotLock)751 RecMutex::Lock::Lock(RecMutex& mutex, NotLock)
752 :
753   mutex_  (mutex),
754   locked_ (false)
755 {}
756 
757 inline
Lock(RecMutex & mutex,TryLock)758 RecMutex::Lock::Lock(RecMutex& mutex, TryLock)
759 :
760   mutex_  (mutex),
761   locked_ (mutex.trylock())
762 {}
763 
764 inline
~Lock()765 RecMutex::Lock::~Lock()
766 {
767   if(locked_)
768     mutex_.unlock();
769 }
770 
771 inline
acquire()772 void RecMutex::Lock::acquire()
773 {
774   mutex_.lock();
775   locked_ = true;
776 }
777 
778 inline
try_acquire()779 bool RecMutex::Lock::try_acquire()
780 {
781   locked_ = mutex_.trylock();
782   return locked_;
783 }
784 
785 inline
release()786 void RecMutex::Lock::release()
787 {
788   mutex_.unlock();
789   locked_ = false;
790 }
791 
792 inline
locked()793 bool RecMutex::Lock::locked() const
794 {
795   return locked_;
796 }
797 
798 
799 /**** Glib::Threads::RWLock::ReaderLock ************************************/
800 
801 inline
ReaderLock(RWLock & rwlock)802 RWLock::ReaderLock::ReaderLock(RWLock& rwlock)
803 :
804   rwlock_ (rwlock),
805   locked_ (true)
806 {
807   rwlock_.reader_lock();
808 }
809 
810 inline
ReaderLock(RWLock & rwlock,NotLock)811 RWLock::ReaderLock::ReaderLock(RWLock& rwlock, NotLock)
812 :
813   rwlock_ (rwlock),
814   locked_ (false)
815 {}
816 
817 inline
ReaderLock(RWLock & rwlock,TryLock)818 RWLock::ReaderLock::ReaderLock(RWLock& rwlock, TryLock)
819 :
820   rwlock_ (rwlock),
821   locked_ (rwlock.reader_trylock())
822 {}
823 
824 inline
~ReaderLock()825 RWLock::ReaderLock::~ReaderLock()
826 {
827   if(locked_)
828     rwlock_.reader_unlock();
829 }
830 
831 inline
acquire()832 void RWLock::ReaderLock::acquire()
833 {
834   rwlock_.reader_lock();
835   locked_ = true;
836 }
837 
838 inline
try_acquire()839 bool RWLock::ReaderLock::try_acquire()
840 {
841   locked_ = rwlock_.reader_trylock();
842   return locked_;
843 }
844 
845 inline
release()846 void RWLock::ReaderLock::release()
847 {
848   rwlock_.reader_unlock();
849   locked_ = false;
850 }
851 
852 inline
locked()853 bool RWLock::ReaderLock::locked() const
854 {
855   return locked_;
856 }
857 
858 
859 /**** Glib::Threads::RWLock::WriterLock ************************************/
860 
861 inline
WriterLock(RWLock & rwlock)862 RWLock::WriterLock::WriterLock(RWLock& rwlock)
863 :
864   rwlock_ (rwlock),
865   locked_ (true)
866 {
867   rwlock_.writer_lock();
868 }
869 
870 inline
WriterLock(RWLock & rwlock,NotLock)871 RWLock::WriterLock::WriterLock(RWLock& rwlock, NotLock)
872 :
873   rwlock_ (rwlock),
874   locked_ (false)
875 {}
876 
877 inline
WriterLock(RWLock & rwlock,TryLock)878 RWLock::WriterLock::WriterLock(RWLock& rwlock, TryLock)
879 :
880   rwlock_ (rwlock),
881   locked_ (rwlock.writer_trylock())
882 {}
883 
884 inline
~WriterLock()885 RWLock::WriterLock::~WriterLock()
886 {
887   if(locked_)
888     rwlock_.writer_unlock();
889 }
890 
891 inline
acquire()892 void RWLock::WriterLock::acquire()
893 {
894   rwlock_.writer_lock();
895   locked_ = true;
896 }
897 
898 inline
try_acquire()899 bool RWLock::WriterLock::try_acquire()
900 {
901   locked_ = rwlock_.writer_trylock();
902   return locked_;
903 }
904 
905 inline
release()906 void RWLock::WriterLock::release()
907 {
908   rwlock_.writer_unlock();
909   locked_ = false;
910 }
911 
912 inline
locked()913 bool RWLock::WriterLock::locked() const
914 {
915   return locked_;
916 }
917 
918 /**** Glib::Threads::Private<T> ********************************************/
919 
920 // static
921 template <class T>
delete_ptr(void * data)922 void Private<T>::delete_ptr(void* data)
923 {
924   delete static_cast<T*>(data);
925 }
926 
927 template <class T> inline
Private(typename Private<T>::DestructorFunc destructor_func)928 Private<T>::Private(typename Private<T>::DestructorFunc destructor_func)
929 {
930   // gobject_ = G_PRIVATE_INIT(destructor_func);
931   // does not compile with --enable-warnings=fatal.
932   // GPrivate is a struct, and G_PRIVATE_INIT is an initializer of type { ... }.
933   // G_PRIVATE_INIT can be used only in initializations.
934   const GPrivate temp = G_PRIVATE_INIT(destructor_func);
935   gobject_ = temp;
936 }
937 
938 template <class T> inline
get()939 T* Private<T>::get()
940 {
941   return static_cast<T*>(g_private_get(&gobject_));
942 }
943 
944 template <class T> inline
set(T * data)945 void Private<T>::set(T* data)
946 {
947   g_private_set(&gobject_, data);
948 }
949 
950 template <class T> inline
replace(T * data)951 void Private<T>::replace(T* data)
952 {
953   g_private_replace(&gobject_, data);
954 }
955 
956 #endif /* DOXYGEN_SHOULD_SKIP_THIS */
957 
958 } //namespace Threads
959 
960 } // namespace Glib
961 
962 
963 #endif // GLIBMM_DISABLE_DEPRECATED
964 
965 
966 #endif /* _GLIBMM_THREADS_H */
967 
968