]> git.proxmox.com Git - mirror_qemu.git/blob - io/channel-watch.c
io: add helper module for creating watches on FDs
[mirror_qemu.git] / io / channel-watch.c
1 /*
2 * QEMU I/O channels watch helper APIs
3 *
4 * Copyright (c) 2015 Red Hat, Inc.
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
18 *
19 */
20
21 #include "io/channel-watch.h"
22
23 typedef struct QIOChannelFDSource QIOChannelFDSource;
24 struct QIOChannelFDSource {
25 GSource parent;
26 GPollFD fd;
27 QIOChannel *ioc;
28 GIOCondition condition;
29 };
30
31
32 typedef struct QIOChannelFDPairSource QIOChannelFDPairSource;
33 struct QIOChannelFDPairSource {
34 GSource parent;
35 GPollFD fdread;
36 GPollFD fdwrite;
37 QIOChannel *ioc;
38 GIOCondition condition;
39 };
40
41
42 static gboolean
43 qio_channel_fd_source_prepare(GSource *source G_GNUC_UNUSED,
44 gint *timeout)
45 {
46 *timeout = -1;
47
48 return FALSE;
49 }
50
51
52 static gboolean
53 qio_channel_fd_source_check(GSource *source)
54 {
55 QIOChannelFDSource *ssource = (QIOChannelFDSource *)source;
56
57 return ssource->fd.revents & ssource->condition;
58 }
59
60
61 static gboolean
62 qio_channel_fd_source_dispatch(GSource *source,
63 GSourceFunc callback,
64 gpointer user_data)
65 {
66 QIOChannelFunc func = (QIOChannelFunc)callback;
67 QIOChannelFDSource *ssource = (QIOChannelFDSource *)source;
68
69 return (*func)(ssource->ioc,
70 ssource->fd.revents & ssource->condition,
71 user_data);
72 }
73
74
75 static void
76 qio_channel_fd_source_finalize(GSource *source)
77 {
78 QIOChannelFDSource *ssource = (QIOChannelFDSource *)source;
79
80 object_unref(OBJECT(ssource->ioc));
81 }
82
83
84 static gboolean
85 qio_channel_fd_pair_source_prepare(GSource *source G_GNUC_UNUSED,
86 gint *timeout)
87 {
88 *timeout = -1;
89
90 return FALSE;
91 }
92
93
94 static gboolean
95 qio_channel_fd_pair_source_check(GSource *source)
96 {
97 QIOChannelFDPairSource *ssource = (QIOChannelFDPairSource *)source;
98 GIOCondition poll_condition = ssource->fdread.revents |
99 ssource->fdwrite.revents;
100
101 return poll_condition & ssource->condition;
102 }
103
104
105 static gboolean
106 qio_channel_fd_pair_source_dispatch(GSource *source,
107 GSourceFunc callback,
108 gpointer user_data)
109 {
110 QIOChannelFunc func = (QIOChannelFunc)callback;
111 QIOChannelFDPairSource *ssource = (QIOChannelFDPairSource *)source;
112 GIOCondition poll_condition = ssource->fdread.revents |
113 ssource->fdwrite.revents;
114
115 return (*func)(ssource->ioc,
116 poll_condition & ssource->condition,
117 user_data);
118 }
119
120
121 static void
122 qio_channel_fd_pair_source_finalize(GSource *source)
123 {
124 QIOChannelFDPairSource *ssource = (QIOChannelFDPairSource *)source;
125
126 object_unref(OBJECT(ssource->ioc));
127 }
128
129
130 GSourceFuncs qio_channel_fd_source_funcs = {
131 qio_channel_fd_source_prepare,
132 qio_channel_fd_source_check,
133 qio_channel_fd_source_dispatch,
134 qio_channel_fd_source_finalize
135 };
136
137
138 GSourceFuncs qio_channel_fd_pair_source_funcs = {
139 qio_channel_fd_pair_source_prepare,
140 qio_channel_fd_pair_source_check,
141 qio_channel_fd_pair_source_dispatch,
142 qio_channel_fd_pair_source_finalize
143 };
144
145
146 GSource *qio_channel_create_fd_watch(QIOChannel *ioc,
147 int fd,
148 GIOCondition condition)
149 {
150 GSource *source;
151 QIOChannelFDSource *ssource;
152
153 source = g_source_new(&qio_channel_fd_source_funcs,
154 sizeof(QIOChannelFDSource));
155 ssource = (QIOChannelFDSource *)source;
156
157 ssource->ioc = ioc;
158 object_ref(OBJECT(ioc));
159
160 ssource->condition = condition;
161
162 ssource->fd.fd = fd;
163 ssource->fd.events = condition;
164
165 g_source_add_poll(source, &ssource->fd);
166
167 return source;
168 }
169
170
171 GSource *qio_channel_create_fd_pair_watch(QIOChannel *ioc,
172 int fdread,
173 int fdwrite,
174 GIOCondition condition)
175 {
176 GSource *source;
177 QIOChannelFDPairSource *ssource;
178
179 source = g_source_new(&qio_channel_fd_pair_source_funcs,
180 sizeof(QIOChannelFDPairSource));
181 ssource = (QIOChannelFDPairSource *)source;
182
183 ssource->ioc = ioc;
184 object_ref(OBJECT(ioc));
185
186 ssource->condition = condition;
187
188 ssource->fdread.fd = fdread;
189 ssource->fdread.events = condition & G_IO_IN;
190
191 ssource->fdwrite.fd = fdwrite;
192 ssource->fdwrite.events = condition & G_IO_OUT;
193
194 g_source_add_poll(source, &ssource->fdread);
195 g_source_add_poll(source, &ssource->fdwrite);
196
197 return source;
198 }