]>
Commit | Line | Data |
---|---|---|
d63c9477 AL |
1 | /* |
2 | * GLIB Compatibility Functions | |
3 | * | |
4 | * Copyright IBM, Corp. 2013 | |
5 | * | |
6 | * Authors: | |
7 | * Anthony Liguori <[email protected]> | |
86946a2d MT |
8 | * Michael Tokarev <[email protected]> |
9 | * Paolo Bonzini <[email protected]> | |
d63c9477 AL |
10 | * |
11 | * This work is licensed under the terms of the GNU GPL, version 2 or later. | |
12 | * See the COPYING file in the top-level directory. | |
13 | * | |
14 | */ | |
15 | ||
16 | #ifndef QEMU_GLIB_COMPAT_H | |
17 | #define QEMU_GLIB_COMPAT_H | |
18 | ||
19 | #include <glib.h> | |
20 | ||
21 | #if !GLIB_CHECK_VERSION(2, 14, 0) | |
22 | static inline guint g_timeout_add_seconds(guint interval, GSourceFunc function, | |
23 | gpointer data) | |
24 | { | |
25 | return g_timeout_add(interval * 1000, function, data); | |
26 | } | |
27 | #endif | |
28 | ||
5a007547 SP |
29 | #ifdef _WIN32 |
30 | /* | |
31 | * g_poll has a problem on Windows when using | |
32 | * timeouts < 10ms, so use wrapper. | |
33 | */ | |
34 | #define g_poll(fds, nfds, timeout) g_poll_fixed(fds, nfds, timeout) | |
35 | gint g_poll_fixed(GPollFD *fds, guint nfds, gint timeout); | |
36 | #elif !GLIB_CHECK_VERSION(2, 20, 0) | |
f95c967a SH |
37 | /* |
38 | * Glib before 2.20.0 doesn't implement g_poll, so wrap it to compile properly | |
39 | * on older systems. | |
40 | */ | |
41 | static inline gint g_poll(GPollFD *fds, guint nfds, gint timeout) | |
42 | { | |
43 | GMainContext *ctx = g_main_context_default(); | |
44 | return g_main_context_get_poll_func(ctx)(fds, nfds, timeout); | |
45 | } | |
46 | #endif | |
47 | ||
86946a2d MT |
48 | #if !GLIB_CHECK_VERSION(2, 31, 0) |
49 | /* before glib-2.31, GMutex and GCond was dynamic-only (there was a separate | |
50 | * GStaticMutex, but it didn't work with condition variables). | |
51 | * | |
52 | * Our implementation uses GOnce to fake a static implementation that does | |
53 | * not require separate initialization. | |
54 | * We need to rename the types to avoid passing our CompatGMutex/CompatGCond | |
55 | * by mistake to a function that expects GMutex/GCond. However, for ease | |
56 | * of use we keep the GLib function names. GLib uses macros for the | |
57 | * implementation, we use inline functions instead and undefine the macros. | |
58 | */ | |
59 | ||
60 | typedef struct CompatGMutex { | |
61 | GOnce once; | |
62 | } CompatGMutex; | |
63 | ||
64 | typedef struct CompatGCond { | |
65 | GOnce once; | |
66 | } CompatGCond; | |
67 | ||
68 | static inline gpointer do_g_mutex_new(gpointer unused) | |
69 | { | |
70 | return (gpointer) g_mutex_new(); | |
71 | } | |
72 | ||
73 | static inline void g_mutex_init(CompatGMutex *mutex) | |
74 | { | |
75 | mutex->once = (GOnce) G_ONCE_INIT; | |
76 | } | |
77 | ||
78 | static inline void g_mutex_clear(CompatGMutex *mutex) | |
79 | { | |
80 | assert(mutex->once.status != G_ONCE_STATUS_PROGRESS); | |
81 | if (mutex->once.retval) { | |
82 | g_mutex_free((GMutex *) mutex->once.retval); | |
83 | } | |
84 | mutex->once = (GOnce) G_ONCE_INIT; | |
85 | } | |
86 | ||
87 | static inline void (g_mutex_lock)(CompatGMutex *mutex) | |
88 | { | |
89 | g_once(&mutex->once, do_g_mutex_new, NULL); | |
90 | g_mutex_lock((GMutex *) mutex->once.retval); | |
91 | } | |
92 | #undef g_mutex_lock | |
93 | ||
94 | static inline gboolean (g_mutex_trylock)(CompatGMutex *mutex) | |
95 | { | |
96 | g_once(&mutex->once, do_g_mutex_new, NULL); | |
97 | return g_mutex_trylock((GMutex *) mutex->once.retval); | |
98 | } | |
99 | #undef g_mutex_trylock | |
100 | ||
101 | ||
102 | static inline void (g_mutex_unlock)(CompatGMutex *mutex) | |
103 | { | |
104 | g_mutex_unlock((GMutex *) mutex->once.retval); | |
105 | } | |
106 | #undef g_mutex_unlock | |
107 | ||
108 | static inline gpointer do_g_cond_new(gpointer unused) | |
109 | { | |
110 | return (gpointer) g_cond_new(); | |
111 | } | |
112 | ||
113 | static inline void g_cond_init(CompatGCond *cond) | |
114 | { | |
115 | cond->once = (GOnce) G_ONCE_INIT; | |
116 | } | |
117 | ||
118 | static inline void g_cond_clear(CompatGCond *cond) | |
119 | { | |
120 | assert(cond->once.status != G_ONCE_STATUS_PROGRESS); | |
121 | if (cond->once.retval) { | |
122 | g_cond_free((GCond *) cond->once.retval); | |
123 | } | |
124 | cond->once = (GOnce) G_ONCE_INIT; | |
125 | } | |
126 | ||
127 | static inline void (g_cond_wait)(CompatGCond *cond, CompatGMutex *mutex) | |
128 | { | |
129 | assert(mutex->once.status != G_ONCE_STATUS_PROGRESS); | |
130 | g_once(&cond->once, do_g_cond_new, NULL); | |
131 | g_cond_wait((GCond *) cond->once.retval, (GMutex *) mutex->once.retval); | |
132 | } | |
133 | #undef g_cond_wait | |
134 | ||
135 | static inline void (g_cond_broadcast)(CompatGCond *cond) | |
136 | { | |
137 | g_once(&cond->once, do_g_cond_new, NULL); | |
138 | g_cond_broadcast((GCond *) cond->once.retval); | |
139 | } | |
140 | #undef g_cond_broadcast | |
141 | ||
142 | static inline void (g_cond_signal)(CompatGCond *cond) | |
143 | { | |
144 | g_once(&cond->once, do_g_cond_new, NULL); | |
145 | g_cond_signal((GCond *) cond->once.retval); | |
146 | } | |
147 | #undef g_cond_signal | |
148 | ||
149 | ||
150 | /* before 2.31 there was no g_thread_new() */ | |
151 | static inline GThread *g_thread_new(const char *name, | |
152 | GThreadFunc func, gpointer data) | |
153 | { | |
154 | GThread *thread = g_thread_create(func, data, TRUE, NULL); | |
155 | if (!thread) { | |
156 | g_error("creating thread"); | |
157 | } | |
158 | return thread; | |
159 | } | |
160 | #else | |
161 | #define CompatGMutex GMutex | |
162 | #define CompatGCond GCond | |
163 | #endif /* glib 2.31 */ | |
164 | ||
d63c9477 | 165 | #endif |