1
/**************************************************************************
3
(C) 2008 - 2011 Alexander Shaduri <ashaduri 'at' gmail.com>
4
License: See LICENSE_zlib.txt file
5
***************************************************************************/
7
#ifndef HZ_SYNC_POLICY_GLIB_H
8
#define HZ_SYNC_POLICY_GLIB_H
10
#include "hz_config.h" // feature macros
20
// Note: g_static_mutex_*lock() functions may give warnings about breaking strict-aliasing rules.
21
// The warnings are completely harmless and visible on some versions of glib only.
22
// However, due to their number, I decided to implement this workaround.
25
// same as stock version, but an additional cast to (void*) is added.
26
#define hz_glib_static_mutex_get_mutex(mutex) \
27
( g_thread_use_default_impl ? ((GMutex*) ((void*)((mutex)->static_mutex.pad))) : \
28
g_static_mutex_get_mutex_impl_shortcut(&((mutex)->runtime_mutex)) )
31
// win32 has different definition of this macro, so default to stock version.
32
#define hz_glib_static_mutex_get_mutex(mutex) g_static_mutex_get_mutex(mutex)
36
#define hz_glib_static_mutex_lock(mutex) \
37
g_mutex_lock(hz_glib_static_mutex_get_mutex(mutex))
39
#define hz_glib_static_mutex_trylock(mutex) \
40
g_mutex_trylock(hz_glib_static_mutex_get_mutex(mutex))
42
#define hz_glib_static_mutex_unlock(mutex) \
43
g_mutex_unlock(hz_glib_static_mutex_get_mutex(mutex))
52
class MutexGlib : public hz::noncopyable {
54
typedef GStaticMutex native_type;
56
static void native_lock(native_type& mutex)
58
hz_glib_static_mutex_lock(&mutex);
61
static bool native_trylock(native_type& mutex)
63
return hz_glib_static_mutex_trylock(&mutex);
66
static void native_unlock(native_type& mutex)
68
hz_glib_static_mutex_unlock(&mutex);
71
MutexGlib() { g_static_mutex_init(&mutex_); }
72
~MutexGlib() { g_static_mutex_free(&mutex_); }
74
void lock() { native_lock(mutex_); }
75
bool trylock() { return native_trylock(mutex_); }
76
void unlock() { native_unlock(mutex_); }
79
GStaticMutex mutex_; // use StaticMutex, I think it uses less heap memory
84
class RecMutexGlib : public hz::noncopyable {
86
typedef GStaticRecMutex native_type;
88
static void native_lock(native_type& mutex)
90
g_static_rec_mutex_lock(&mutex);
93
static bool native_trylock(native_type& mutex)
95
return g_static_rec_mutex_trylock(&mutex);
98
static void native_unlock(native_type& mutex)
100
g_static_rec_mutex_unlock(&mutex);
103
RecMutexGlib() { g_static_rec_mutex_init(&mutex_); }
104
~RecMutexGlib() { g_static_rec_mutex_free(&mutex_); }
106
void lock() { native_lock(mutex_); }
107
bool trylock() { return native_trylock(mutex_); }
108
void unlock() { native_unlock(mutex_); }
111
GStaticRecMutex mutex_;
116
class RWMutexGlib : public hz::noncopyable {
118
typedef GStaticRWLock native_type;
120
static void native_lock(native_type& mutex, bool for_write = false)
123
g_static_rw_lock_writer_lock(&mutex);
125
g_static_rw_lock_reader_lock(&mutex);
129
static bool native_trylock(native_type& mutex, bool for_write = false)
131
return (for_write ? g_static_rw_lock_writer_trylock(&mutex) : g_static_rw_lock_reader_trylock(&mutex));
134
static void native_unlock(native_type& mutex, bool for_write = false)
137
g_static_rw_lock_writer_unlock(&mutex);
139
g_static_rw_lock_reader_unlock(&mutex);
143
RWMutexGlib() { g_static_rw_lock_init(&mutex_); }
144
~RWMutexGlib() { g_static_rw_lock_free(&mutex_); }
146
void lock(bool for_write = false) { native_lock(mutex_, for_write); }
147
bool trylock(bool for_write = false) { return native_trylock(mutex_, for_write); }
148
void unlock(bool for_write = false) { native_unlock(mutex_, for_write); }
151
GStaticRWLock mutex_;
157
// Native type notes:
158
// MutexGlib's underlying structure is neither guaranteed to be
159
// recursive nor to be non-recursive.
160
// All these mutexes won't do anything unless gthread is initialized.
162
// Note: For this policy to work, you MUST initialize GThread system
163
// by calling one of the following (doesn't matter which exactly) beforehand:
164
// Glib::thread_init(); // glibmm
166
// g_thread_init(NULL); // glib
168
// SyncPolicyGlib::init(); // sync's wrapper
170
// If you don't do it, the operations will silently do nothing.
173
// Glib doesn't provide any means to detect errors, so no exceptions here.
175
struct SyncPolicyGlib : public SyncScopedLockProvider<SyncPolicyGlib> {
179
typedef MutexGlib Mutex;
180
typedef Mutex::native_type NativeMutex;
182
typedef RecMutexGlib RecMutex;
183
typedef RecMutex::native_type NativeRecMutex;
185
typedef RWMutexGlib RWMutex;
186
typedef RWMutex::native_type NativeRWMutex;
189
typedef GenericScopedLock<Mutex> ScopedLock;
190
typedef GenericScopedTryLock<Mutex> ScopedTryLock;
192
typedef GenericScopedLock<NativeMutex> ScopedNativeLock;
193
typedef GenericScopedTryLock<NativeMutex> ScopedNativeTryLock;
195
typedef GenericScopedLock<RecMutex> ScopedRecLock;
196
typedef GenericScopedTryLock<RecMutex> ScopedRecTryLock;
198
typedef GenericScopedLock<NativeRecMutex> ScopedNativeRecLock;
199
typedef GenericScopedTryLock<NativeRecMutex> ScopedNativeRecTryLock;
201
typedef GenericScopedRWLock<RWMutex> ScopedRWLock;
202
typedef GenericScopedRWTryLock<RWMutex> ScopedRWTryLock;
204
typedef GenericScopedRWLock<NativeRWMutex> ScopedNativeRWLock;
205
typedef GenericScopedRWTryLock<NativeRWMutex> ScopedNativeRWTryLock;
210
// If threads are unavailable, this will abort.
211
static bool init() { if (!g_thread_supported()) g_thread_init(NULL); return true; }
213
static void lock(Mutex& m) { m.lock(); }
214
static bool trylock(Mutex& m) { return m.trylock(); }
215
static void unlock(Mutex& m) { m.unlock(); }
217
static void lock(NativeMutex& m) { Mutex::native_lock(m); }
218
static bool trylock(NativeMutex& m) { return Mutex::native_trylock(m); }
219
static void unlock(NativeMutex& m) { Mutex::native_unlock(m); }
221
static void lock(RecMutex& m) { m.lock(); }
222
static bool trylock(RecMutex& m) { return m.trylock(); }
223
static void unlock(RecMutex& m) { m.unlock(); }
225
static void lock(NativeRecMutex& m) { RecMutex::native_lock(m); }
226
static bool trylock(NativeRecMutex& m) { return RecMutex::native_trylock(m); }
227
static void unlock(NativeRecMutex& m) { RecMutex::native_unlock(m); }
229
static void lock(RWMutex& m, bool for_write = false) { m.lock(for_write); }
230
static bool trylock(RWMutex& m, bool for_write = false) { return m.trylock(for_write); }
231
static void unlock(RWMutex& m, bool for_write = false) { m.unlock(for_write); }
233
static void lock(NativeRWMutex& m, bool for_write = false) { RWMutex::native_lock(m, for_write); }
234
static bool trylock(NativeRWMutex& m, bool for_write = false) { return RWMutex::native_trylock(m, for_write); }
235
static void unlock(NativeRWMutex& m, bool for_write = false) { RWMutex::native_unlock(m, for_write); }
243
template<> struct SyncGetPolicy<SyncPolicyGlib::Mutex> { typedef SyncPolicyGlib type; };
244
template<> struct SyncGetPolicy<SyncPolicyGlib::NativeMutex> { typedef SyncPolicyGlib type; };
245
template<> struct SyncGetPolicy<SyncPolicyGlib::RecMutex> { typedef SyncPolicyGlib type; };
246
template<> struct SyncGetPolicy<SyncPolicyGlib::NativeRecMutex> { typedef SyncPolicyGlib type; };
247
template<> struct SyncGetPolicy<SyncPolicyGlib::RWMutex> { typedef SyncPolicyGlib type; };
248
template<> struct SyncGetPolicy<SyncPolicyGlib::NativeRWMutex> { typedef SyncPolicyGlib type; };