GSettings docs: clarify what is a good path
[glib.git] / glib / gwakeup.c
blobbb490594f0eae116f3f061a45f764b2a6955ae34
1 /*
2 * Copyright © 2011 Canonical Limited
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the licence, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
19 * Author: Ryan Lortie <desrt@desrt.ca>
22 #include "config.h"
25 /* gwakeup.h is special -- GIO and some test cases include it. As such,
26 * it cannot include other glib headers without triggering the single
27 * includes warnings. We have to manually include its dependencies here
28 * (and at all other use sites).
30 #ifdef GLIB_COMPILATION
31 #include "gtypes.h"
32 #include "gpoll.h"
33 #else
34 #include <glib.h>
35 #endif
37 #include "gwakeup.h"
39 /*< private >
40 * SECTION:gwakeup
41 * @title: GWakeup
42 * @short_description: portable cross-thread event signal mechanism
44 * #GWakeup is a simple and portable way of signaling events between
45 * different threads in a way that integrates nicely with g_poll().
46 * GLib uses it internally for cross-thread signalling in the
47 * implementation of #GMainContext and #GCancellable.
49 * You first create a #GWakeup with g_wakeup_new() and initialise a
50 * #GPollFD from it using g_wakeup_get_pollfd(). Polling on the created
51 * #GPollFD will block until g_wakeup_signal() is called, at which point
52 * it will immediately return. Future attempts to poll will continue to
53 * return until g_wakeup_acknowledge() is called. g_wakeup_free() is
54 * used to free a #GWakeup.
56 * On sufficiently modern Linux, this is implemented using eventfd. On
57 * Windows it is implemented using an event handle. On other systems it
58 * is implemented with a pair of pipes.
60 * Since: 2.30
61 **/
62 #ifdef _WIN32
64 #include <windows.h>
66 #ifdef GLIB_COMPILATION
67 #include "gmessages.h"
68 #include "giochannel.h"
69 #include "gwin32.h"
70 #endif
72 GWakeup *
73 g_wakeup_new (void)
75 HANDLE wakeup;
77 wakeup = CreateEvent (NULL, TRUE, FALSE, NULL);
79 if (wakeup == NULL)
80 g_error ("Cannot create event for GWakeup: %s",
81 g_win32_error_message (GetLastError ()));
83 return (GWakeup *) wakeup;
86 void
87 g_wakeup_get_pollfd (GWakeup *wakeup,
88 GPollFD *poll_fd)
90 poll_fd->fd = (gintptr) wakeup;
91 poll_fd->events = G_IO_IN;
94 void
95 g_wakeup_acknowledge (GWakeup *wakeup)
97 ResetEvent ((HANDLE) wakeup);
100 void
101 g_wakeup_signal (GWakeup *wakeup)
103 SetEvent ((HANDLE) wakeup);
106 void
107 g_wakeup_free (GWakeup *wakeup)
109 CloseHandle ((HANDLE) wakeup);
112 #else
114 #include "glib-unix.h"
115 #include <fcntl.h>
117 #if defined (HAVE_EVENTFD)
118 #include <sys/eventfd.h>
119 #endif
121 struct _GWakeup
123 gint fds[2];
127 * g_wakeup_new:
129 * Creates a new #GWakeup.
131 * You should use g_wakeup_free() to free it when you are done.
133 * Returns: a new #GWakeup
135 * Since: 2.30
137 GWakeup *
138 g_wakeup_new (void)
140 GError *error = NULL;
141 GWakeup *wakeup;
143 wakeup = g_slice_new (GWakeup);
145 /* try eventfd first, if we think we can */
146 #if defined (HAVE_EVENTFD)
147 #ifndef TEST_EVENTFD_FALLBACK
148 wakeup->fds[0] = eventfd (0, EFD_CLOEXEC | EFD_NONBLOCK);
149 #else
150 wakeup->fds[0] = -1;
151 #endif
153 if (wakeup->fds[0] != -1)
155 wakeup->fds[1] = -1;
156 return wakeup;
159 /* for any failure, try a pipe instead */
160 #endif
162 if (!g_unix_open_pipe (wakeup->fds, FD_CLOEXEC, &error))
163 g_error ("Creating pipes for GWakeup: %s\n", error->message);
165 if (!g_unix_set_fd_nonblocking (wakeup->fds[0], TRUE, &error) ||
166 !g_unix_set_fd_nonblocking (wakeup->fds[1], TRUE, &error))
167 g_error ("Set pipes non-blocking for GWakeup: %s\n", error->message);
169 return wakeup;
173 * g_wakeup_get_pollfd:
174 * @wakeup: a #GWakeup
175 * @poll_fd: a #GPollFD
177 * Prepares a @poll_fd such that polling on it will succeed when
178 * g_wakeup_signal() has been called on @wakeup.
180 * @poll_fd is valid until @wakeup is freed.
182 * Since: 2.30
184 void
185 g_wakeup_get_pollfd (GWakeup *wakeup,
186 GPollFD *poll_fd)
188 poll_fd->fd = wakeup->fds[0];
189 poll_fd->events = G_IO_IN;
193 * g_wakeup_acknowledge:
194 * @wakeup: a #GWakeup
196 * Acknowledges receipt of a wakeup signal on @wakeup.
198 * You must call this after @wakeup polls as ready. If not, it will
199 * continue to poll as ready until you do so.
201 * If you call this function and @wakeup is not signaled, nothing
202 * happens.
204 * Since: 2.30
206 void
207 g_wakeup_acknowledge (GWakeup *wakeup)
209 char buffer[16];
211 /* read until it is empty */
212 while (read (wakeup->fds[0], buffer, sizeof buffer) == sizeof buffer);
216 * g_wakeup_signal:
217 * @wakeup: a #GWakeup
219 * Signals @wakeup.
221 * Any future (or present) polling on the #GPollFD returned by
222 * g_wakeup_get_pollfd() will immediately succeed until such a time as
223 * g_wakeup_acknowledge() is called.
225 * This function is safe to call from a UNIX signal handler.
227 * Since: 2.30
229 void
230 g_wakeup_signal (GWakeup *wakeup)
232 guint64 one = 1;
234 if (wakeup->fds[1] == -1)
235 write (wakeup->fds[0], &one, sizeof one);
236 else
237 write (wakeup->fds[1], &one, 1);
241 * g_wakeup_free:
242 * @wakeup: a #GWakeup
244 * Frees @wakeup.
246 * You must not currently be polling on the #GPollFD returned by
247 * g_wakeup_get_pollfd(), or the result is undefined.
249 void
250 g_wakeup_free (GWakeup *wakeup)
252 close (wakeup->fds[0]);
254 if (wakeup->fds[1] != -1)
255 close (wakeup->fds[1]);
257 g_slice_free (GWakeup, wakeup);
260 #endif /* !_WIN32 */