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