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 --
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