]> Git Repo - qemu.git/blob - include/glib-compat.h
Merge remote-tracking branch 'remotes/kraxel/tags/pull-console-20141015-1' into staging
[qemu.git] / include / glib-compat.h
1 /*
2  * GLIB Compatibility Functions
3  *
4  * Copyright IBM, Corp. 2013
5  *
6  * Authors:
7  *  Anthony Liguori   <[email protected]>
8  *  Michael Tokarev   <[email protected]>
9  *  Paolo Bonzini     <[email protected]>
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 /* GLIB version compatibility flags */
22 #if !GLIB_CHECK_VERSION(2, 26, 0)
23 #define G_TIME_SPAN_SECOND              (G_GINT64_CONSTANT(1000000))
24 #endif
25
26 #if !GLIB_CHECK_VERSION(2, 14, 0)
27 static inline guint g_timeout_add_seconds(guint interval, GSourceFunc function,
28                                           gpointer data)
29 {
30     return g_timeout_add(interval * 1000, function, data);
31 }
32 #endif
33
34 #if !GLIB_CHECK_VERSION(2, 28, 0)
35 static inline gint64 g_get_monotonic_time(void)
36 {
37     /* g_get_monotonic_time() is best-effort so we can use the wall clock as a
38      * fallback.
39      */
40
41     GTimeVal time;
42     g_get_current_time(&time);
43
44     return time.tv_sec * G_TIME_SPAN_SECOND + time.tv_usec;
45 }
46 #endif
47
48 #if !GLIB_CHECK_VERSION(2, 16, 0)
49 static inline int g_strcmp0(const char *str1, const char *str2)
50 {
51     int result;
52
53     if (!str1) {
54         result = -(str1 != str2);
55     } else if (!str2) {
56         result = (str1 != str2);
57     } else {
58         result = strcmp(str1, str2);
59     }
60
61     return result;
62 }
63 #endif
64
65 #ifdef _WIN32
66 /*
67  * g_poll has a problem on Windows when using
68  * timeouts < 10ms, so use wrapper.
69  */
70 #define g_poll(fds, nfds, timeout) g_poll_fixed(fds, nfds, timeout)
71 gint g_poll_fixed(GPollFD *fds, guint nfds, gint timeout);
72 #elif !GLIB_CHECK_VERSION(2, 20, 0)
73 /*
74  * Glib before 2.20.0 doesn't implement g_poll, so wrap it to compile properly
75  * on older systems.
76  */
77 static inline gint g_poll(GPollFD *fds, guint nfds, gint timeout)
78 {
79     GMainContext *ctx = g_main_context_default();
80     return g_main_context_get_poll_func(ctx)(fds, nfds, timeout);
81 }
82 #endif
83
84 #if !GLIB_CHECK_VERSION(2, 31, 0)
85 /* before glib-2.31, GMutex and GCond was dynamic-only (there was a separate
86  * GStaticMutex, but it didn't work with condition variables).
87  *
88  * Our implementation uses GOnce to fake a static implementation that does
89  * not require separate initialization.
90  * We need to rename the types to avoid passing our CompatGMutex/CompatGCond
91  * by mistake to a function that expects GMutex/GCond.  However, for ease
92  * of use we keep the GLib function names.  GLib uses macros for the
93  * implementation, we use inline functions instead and undefine the macros.
94  */
95
96 typedef struct CompatGMutex {
97     GOnce once;
98 } CompatGMutex;
99
100 typedef struct CompatGCond {
101     GOnce once;
102 } CompatGCond;
103
104 static inline gpointer do_g_mutex_new(gpointer unused)
105 {
106     return (gpointer) g_mutex_new();
107 }
108
109 static inline void g_mutex_init(CompatGMutex *mutex)
110 {
111     mutex->once = (GOnce) G_ONCE_INIT;
112 }
113
114 static inline void g_mutex_clear(CompatGMutex *mutex)
115 {
116     assert(mutex->once.status != G_ONCE_STATUS_PROGRESS);
117     if (mutex->once.retval) {
118         g_mutex_free((GMutex *) mutex->once.retval);
119     }
120     mutex->once = (GOnce) G_ONCE_INIT;
121 }
122
123 static inline void (g_mutex_lock)(CompatGMutex *mutex)
124 {
125     g_once(&mutex->once, do_g_mutex_new, NULL);
126     g_mutex_lock((GMutex *) mutex->once.retval);
127 }
128 #undef g_mutex_lock
129
130 static inline gboolean (g_mutex_trylock)(CompatGMutex *mutex)
131 {
132     g_once(&mutex->once, do_g_mutex_new, NULL);
133     return g_mutex_trylock((GMutex *) mutex->once.retval);
134 }
135 #undef g_mutex_trylock
136
137
138 static inline void (g_mutex_unlock)(CompatGMutex *mutex)
139 {
140     g_mutex_unlock((GMutex *) mutex->once.retval);
141 }
142 #undef g_mutex_unlock
143
144 static inline gpointer do_g_cond_new(gpointer unused)
145 {
146     return (gpointer) g_cond_new();
147 }
148
149 static inline void g_cond_init(CompatGCond *cond)
150 {
151     cond->once = (GOnce) G_ONCE_INIT;
152 }
153
154 static inline void g_cond_clear(CompatGCond *cond)
155 {
156     assert(cond->once.status != G_ONCE_STATUS_PROGRESS);
157     if (cond->once.retval) {
158         g_cond_free((GCond *) cond->once.retval);
159     }
160     cond->once = (GOnce) G_ONCE_INIT;
161 }
162
163 static inline void (g_cond_wait)(CompatGCond *cond, CompatGMutex *mutex)
164 {
165     assert(mutex->once.status != G_ONCE_STATUS_PROGRESS);
166     g_once(&cond->once, do_g_cond_new, NULL);
167     g_cond_wait((GCond *) cond->once.retval, (GMutex *) mutex->once.retval);
168 }
169 #undef g_cond_wait
170
171 static inline void (g_cond_broadcast)(CompatGCond *cond)
172 {
173     g_once(&cond->once, do_g_cond_new, NULL);
174     g_cond_broadcast((GCond *) cond->once.retval);
175 }
176 #undef g_cond_broadcast
177
178 static inline void (g_cond_signal)(CompatGCond *cond)
179 {
180     g_once(&cond->once, do_g_cond_new, NULL);
181     g_cond_signal((GCond *) cond->once.retval);
182 }
183 #undef g_cond_signal
184
185
186 /* before 2.31 there was no g_thread_new() */
187 static inline GThread *g_thread_new(const char *name,
188                                     GThreadFunc func, gpointer data)
189 {
190     GThread *thread = g_thread_create(func, data, TRUE, NULL);
191     if (!thread) {
192         g_error("creating thread");
193     }
194     return thread;
195 }
196 #else
197 #define CompatGMutex GMutex
198 #define CompatGCond GCond
199 #endif /* glib 2.31 */
200
201 #endif
This page took 0.034553 seconds and 4 git commands to generate.