~ubuntu-branches/ubuntu/vivid/ardour/vivid-proposed

« back to all changes in this revision

Viewing changes to libs/glibmm2/glibmm/thread.h

  • Committer: Package Import Robot
  • Author(s): Felipe Sateler, Jaromír Mikeš, Felipe Sateler
  • Date: 2014-05-22 14:39:25 UTC
  • mfrom: (29 sid)
  • mto: This revision was merged to the branch mainline in revision 30.
  • Revision ID: package-import@ubuntu.com-20140522143925-vwqfo9287pmkrroe
Tags: 1:2.8.16+git20131003-3
* Team upload

[ Jaromír Mikeš ]
* Add -dbg package

[ Felipe Sateler ]
* Upload to experimental

Show diffs side-by-side

added added

removed removed

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