Branch data Line data Source code
1 : : /* GIO - GLib Input, Output and Streaming Library
2 : : *
3 : : * Copyright (C) 2010 Red Hat, Inc.
4 : : *
5 : : * SPDX-License-Identifier: LGPL-2.1-or-later
6 : : *
7 : : * This library is free software; you can redistribute it and/or
8 : : * modify it under the terms of the GNU Lesser General Public
9 : : * License as published by the Free Software Foundation; either
10 : : * version 2.1 of the License, or (at your option) any later version.
11 : : *
12 : : * This library is distributed in the hope that it will be useful,
13 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 : : * Lesser General Public License for more details.
16 : : *
17 : : * You should have received a copy of the GNU Lesser General
18 : : * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
19 : : */
20 : :
21 : : #include "config.h"
22 : :
23 : : #include <errno.h>
24 : :
25 : : #include "gpollableinputstream.h"
26 : : #include "gasynchelper.h"
27 : : #include "glibintl.h"
28 : :
29 : : /**
30 : : * GPollableInputStream:
31 : : *
32 : : * `GPollableInputStream` is implemented by [class@Gio.InputStream]s that
33 : : * can be polled for readiness to read. This can be used when
34 : : * interfacing with a non-GIO API that expects
35 : : * UNIX-file-descriptor-style asynchronous I/O rather than GIO-style.
36 : : *
37 : : * Some classes may implement `GPollableInputStream` but have only certain
38 : : * instances of that class be pollable. If [method@Gio.PollableInputStream.can_poll]
39 : : * returns false, then the behavior of other `GPollableInputStream` methods is
40 : : * undefined.
41 : : *
42 : : * Since: 2.28
43 : : */
44 : :
45 : 190584 : G_DEFINE_INTERFACE (GPollableInputStream, g_pollable_input_stream, G_TYPE_INPUT_STREAM)
46 : :
47 : : static gboolean g_pollable_input_stream_default_can_poll (GPollableInputStream *stream);
48 : : static gssize g_pollable_input_stream_default_read_nonblocking (GPollableInputStream *stream,
49 : : void *buffer,
50 : : gsize count,
51 : : GError **error);
52 : :
53 : : static void
54 : 146 : g_pollable_input_stream_default_init (GPollableInputStreamInterface *iface)
55 : : {
56 : 146 : iface->can_poll = g_pollable_input_stream_default_can_poll;
57 : 146 : iface->read_nonblocking = g_pollable_input_stream_default_read_nonblocking;
58 : 146 : }
59 : :
60 : : static gboolean
61 : 472 : g_pollable_input_stream_default_can_poll (GPollableInputStream *stream)
62 : : {
63 : 472 : return TRUE;
64 : : }
65 : :
66 : : /**
67 : : * g_pollable_input_stream_can_poll:
68 : : * @stream: a #GPollableInputStream.
69 : : *
70 : : * Checks if @stream is actually pollable. Some classes may implement
71 : : * #GPollableInputStream but have only certain instances of that class
72 : : * be pollable. If this method returns %FALSE, then the behavior of
73 : : * other #GPollableInputStream methods is undefined.
74 : : *
75 : : * For any given stream, the value returned by this method is constant;
76 : : * a stream cannot switch from pollable to non-pollable or vice versa.
77 : : *
78 : : * Returns: %TRUE if @stream is pollable, %FALSE if not.
79 : : *
80 : : * Since: 2.28
81 : : */
82 : : gboolean
83 : 21973 : g_pollable_input_stream_can_poll (GPollableInputStream *stream)
84 : : {
85 : 21973 : g_return_val_if_fail (G_IS_POLLABLE_INPUT_STREAM (stream), FALSE);
86 : :
87 : 21973 : return G_POLLABLE_INPUT_STREAM_GET_INTERFACE (stream)->can_poll (stream);
88 : : }
89 : :
90 : : /**
91 : : * g_pollable_input_stream_is_readable:
92 : : * @stream: a #GPollableInputStream.
93 : : *
94 : : * Checks if @stream can be read.
95 : : *
96 : : * Note that some stream types may not be able to implement this 100%
97 : : * reliably, and it is possible that a call to g_input_stream_read()
98 : : * after this returns %TRUE would still block. To guarantee
99 : : * non-blocking behavior, you should always use
100 : : * g_pollable_input_stream_read_nonblocking(), which will return a
101 : : * %G_IO_ERROR_WOULD_BLOCK error rather than blocking.
102 : : *
103 : : * The behaviour of this method is undefined if
104 : : * g_pollable_input_stream_can_poll() returns %FALSE for @stream.
105 : : *
106 : : * Returns: %TRUE if @stream is readable, %FALSE if not. If an error
107 : : * has occurred on @stream, this will result in
108 : : * g_pollable_input_stream_is_readable() returning %TRUE, and the
109 : : * next attempt to read will return the error.
110 : : *
111 : : * Since: 2.28
112 : : */
113 : : gboolean
114 : 21958 : g_pollable_input_stream_is_readable (GPollableInputStream *stream)
115 : : {
116 : 21958 : g_return_val_if_fail (G_IS_POLLABLE_INPUT_STREAM (stream), FALSE);
117 : :
118 : 21958 : return G_POLLABLE_INPUT_STREAM_GET_INTERFACE (stream)->is_readable (stream);
119 : : }
120 : :
121 : : /**
122 : : * g_pollable_input_stream_create_source:
123 : : * @stream: a #GPollableInputStream.
124 : : * @cancellable: (nullable): a #GCancellable, or %NULL
125 : : *
126 : : * Creates a #GSource that triggers when @stream can be read, or
127 : : * @cancellable is triggered or an error occurs. The callback on the
128 : : * source is of the #GPollableSourceFunc type.
129 : : *
130 : : * As with g_pollable_input_stream_is_readable(), it is possible that
131 : : * the stream may not actually be readable even after the source
132 : : * triggers, so you should use g_pollable_input_stream_read_nonblocking()
133 : : * rather than g_input_stream_read() from the callback.
134 : : *
135 : : * The behaviour of this method is undefined if
136 : : * g_pollable_input_stream_can_poll() returns %FALSE for @stream.
137 : : *
138 : : * Returns: (transfer full): a new #GSource
139 : : *
140 : : * Since: 2.28
141 : : */
142 : : GSource *
143 : 7109 : g_pollable_input_stream_create_source (GPollableInputStream *stream,
144 : : GCancellable *cancellable)
145 : : {
146 : 7109 : g_return_val_if_fail (G_IS_POLLABLE_INPUT_STREAM (stream), NULL);
147 : :
148 : 7109 : return G_POLLABLE_INPUT_STREAM_GET_INTERFACE (stream)->
149 : : create_source (stream, cancellable);
150 : : }
151 : :
152 : : static gssize
153 : 21763 : g_pollable_input_stream_default_read_nonblocking (GPollableInputStream *stream,
154 : : void *buffer,
155 : : gsize count,
156 : : GError **error)
157 : : {
158 : 21763 : if (!g_pollable_input_stream_is_readable (stream))
159 : : {
160 : 7111 : g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK,
161 : : g_strerror (EAGAIN));
162 : 7111 : return -1;
163 : : }
164 : :
165 : 14652 : return G_INPUT_STREAM_GET_CLASS (stream)->
166 : 14652 : read_fn (G_INPUT_STREAM (stream), buffer, count, NULL, error);
167 : : }
168 : :
169 : : /**
170 : : * g_pollable_input_stream_read_nonblocking: (virtual read_nonblocking)
171 : : * @stream: a #GPollableInputStream
172 : : * @buffer: (array length=count) (element-type guint8) (out caller-allocates): a
173 : : * buffer to read data into (which should be at least @count bytes long).
174 : : * @count: (in): the number of bytes you want to read
175 : : * @cancellable: (nullable): a #GCancellable, or %NULL
176 : : * @error: #GError for error reporting, or %NULL to ignore.
177 : : *
178 : : * Attempts to read up to @count bytes from @stream into @buffer, as
179 : : * with g_input_stream_read(). If @stream is not currently readable,
180 : : * this will immediately return %G_IO_ERROR_WOULD_BLOCK, and you can
181 : : * use g_pollable_input_stream_create_source() to create a #GSource
182 : : * that will be triggered when @stream is readable.
183 : : *
184 : : * Note that since this method never blocks, you cannot actually
185 : : * use @cancellable to cancel it. However, it will return an error
186 : : * if @cancellable has already been cancelled when you call, which
187 : : * may happen if you call this method after a source triggers due
188 : : * to having been cancelled.
189 : : *
190 : : * The behaviour of this method is undefined if
191 : : * g_pollable_input_stream_can_poll() returns %FALSE for @stream.
192 : : *
193 : : * Returns: the number of bytes read, or -1 on error (including
194 : : * %G_IO_ERROR_WOULD_BLOCK).
195 : : */
196 : : gssize
197 : 142 : g_pollable_input_stream_read_nonblocking (GPollableInputStream *stream,
198 : : void *buffer,
199 : : gsize count,
200 : : GCancellable *cancellable,
201 : : GError **error)
202 : : {
203 : : gssize res;
204 : :
205 : 142 : g_return_val_if_fail (G_IS_POLLABLE_INPUT_STREAM (stream), -1);
206 : 142 : g_return_val_if_fail (buffer != NULL, 0);
207 : :
208 : 142 : if (g_cancellable_set_error_if_cancelled (cancellable, error))
209 : 0 : return -1;
210 : :
211 : 142 : if (count == 0)
212 : 0 : return 0;
213 : :
214 : 142 : if (((gssize) count) < 0)
215 : : {
216 : 0 : g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT,
217 : : _("Too large count value passed to %s"), G_STRFUNC);
218 : 0 : return -1;
219 : : }
220 : :
221 : 142 : if (cancellable)
222 : 0 : g_cancellable_push_current (cancellable);
223 : :
224 : 142 : res = G_POLLABLE_INPUT_STREAM_GET_INTERFACE (stream)->
225 : : read_nonblocking (stream, buffer, count, error);
226 : :
227 : 142 : if (cancellable)
228 : 0 : g_cancellable_pop_current (cancellable);
229 : :
230 : 142 : return res;
231 : : }
|