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