00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include <config.h>
00026 #include "dbus-socket-set.h"
00027
00028 #include <dbus/dbus-internals.h>
00029 #include <dbus/dbus-list.h>
00030 #include <dbus/dbus-sysdeps.h>
00031 #include <dbus/dbus-watch.h>
00032
00033 #ifndef DOXYGEN_SHOULD_SKIP_THIS
00034
00035 typedef struct {
00036 DBusSocketSet parent;
00037 DBusPollFD *fds;
00038 int n_fds;
00039 int n_reserved;
00040 int n_allocated;
00041 } DBusSocketSetPoll;
00042
00043 #define REALLOC_INCREMENT 8
00044 #define MINIMUM_SIZE 8
00045
00046
00047 #ifdef DBUS_BUILD_TESTS
00048 #define DEFAULT_SIZE_HINT 1
00049 #else
00050 #define DEFAULT_SIZE_HINT MINIMUM_SIZE
00051 #endif
00052
00053 static inline DBusSocketSetPoll *
00054 socket_set_poll_cast (DBusSocketSet *set)
00055 {
00056 _dbus_assert (set->cls == &_dbus_socket_set_poll_class);
00057 return (DBusSocketSetPoll *) set;
00058 }
00059
00060
00061 static void
00062 socket_set_poll_free (DBusSocketSet *set)
00063 {
00064 DBusSocketSetPoll *self = socket_set_poll_cast (set);
00065
00066 dbus_free (self->fds);
00067 dbus_free (self);
00068 _dbus_verbose ("freed socket set %p\n", self);
00069 }
00070
00071 DBusSocketSet *
00072 _dbus_socket_set_poll_new (int size_hint)
00073 {
00074 DBusSocketSetPoll *ret;
00075
00076 if (size_hint <= 0)
00077 size_hint = DEFAULT_SIZE_HINT;
00078
00079 ret = dbus_new0 (DBusSocketSetPoll, 1);
00080
00081 if (ret == NULL)
00082 return NULL;
00083
00084 ret->parent.cls = &_dbus_socket_set_poll_class;
00085 ret->n_fds = 0;
00086 ret->n_allocated = size_hint;
00087
00088 ret->fds = dbus_new0 (DBusPollFD, size_hint);
00089
00090 if (ret->fds == NULL)
00091 {
00092
00093
00094 socket_set_poll_free ((DBusSocketSet *) ret);
00095 return NULL;
00096 }
00097
00098 _dbus_verbose ("new socket set at %p\n", ret);
00099 return (DBusSocketSet *) ret;
00100 }
00101
00102 static short
00103 watch_flags_to_poll_events (unsigned int flags)
00104 {
00105 short events = 0;
00106
00107 if (flags & DBUS_WATCH_READABLE)
00108 events |= _DBUS_POLLIN;
00109 if (flags & DBUS_WATCH_WRITABLE)
00110 events |= _DBUS_POLLOUT;
00111
00112 return events;
00113 }
00114
00115 static dbus_bool_t
00116 socket_set_poll_add (DBusSocketSet *set,
00117 int fd,
00118 unsigned int flags,
00119 dbus_bool_t enabled)
00120 {
00121 DBusSocketSetPoll *self = socket_set_poll_cast (set);
00122 #ifndef DBUS_DISABLE_ASSERT
00123 int i;
00124
00125 for (i = 0; i < self->n_fds; i++)
00126 _dbus_assert (self->fds[i].fd != fd);
00127 #endif
00128
00129 if (self->n_reserved >= self->n_allocated)
00130 {
00131 DBusPollFD *new_fds = dbus_realloc (self->fds,
00132 sizeof (DBusPollFD) * (self->n_allocated + REALLOC_INCREMENT));
00133
00134 _dbus_verbose ("inflating set %p from %d en/%d res/%d alloc to %d\n",
00135 self, self->n_fds, self->n_reserved, self->n_allocated,
00136 self->n_allocated + REALLOC_INCREMENT);
00137
00138 if (new_fds == NULL)
00139 return FALSE;
00140
00141 self->fds = new_fds;
00142 self->n_allocated += REALLOC_INCREMENT;
00143 }
00144
00145 _dbus_verbose ("before adding fd %d to %p, %d en/%d res/%d alloc\n",
00146 fd, self, self->n_fds, self->n_reserved, self->n_allocated);
00147 _dbus_assert (self->n_reserved >= self->n_fds);
00148 _dbus_assert (self->n_allocated > self->n_reserved);
00149
00150 self->n_reserved++;
00151
00152 if (enabled)
00153 {
00154 self->fds[self->n_fds].fd = fd;
00155 self->fds[self->n_fds].events = watch_flags_to_poll_events (flags);
00156 self->n_fds++;
00157 }
00158
00159 return TRUE;
00160 }
00161
00162 static void
00163 socket_set_poll_enable (DBusSocketSet *set,
00164 int fd,
00165 unsigned int flags)
00166 {
00167 DBusSocketSetPoll *self = socket_set_poll_cast (set);
00168 int i;
00169
00170 for (i = 0; i < self->n_fds; i++)
00171 {
00172 if (self->fds[i].fd == fd)
00173 {
00174 self->fds[i].events = watch_flags_to_poll_events (flags);
00175 return;
00176 }
00177 }
00178
00179
00180 _dbus_assert (self->n_fds < self->n_reserved);
00181 _dbus_assert (self->n_reserved <= self->n_allocated);
00182
00183 self->fds[self->n_fds].fd = fd;
00184 self->fds[self->n_fds].events = watch_flags_to_poll_events (flags);
00185 self->n_fds++;
00186 }
00187
00188 static void
00189 socket_set_poll_disable (DBusSocketSet *set,
00190 int fd)
00191 {
00192 DBusSocketSetPoll *self = socket_set_poll_cast (set);
00193 int i;
00194
00195 for (i = 0; i < self->n_fds; i++)
00196 {
00197 if (self->fds[i].fd == fd)
00198 {
00199 if (i != self->n_fds - 1)
00200 {
00201 self->fds[i].fd = self->fds[self->n_fds - 1].fd;
00202 self->fds[i].events = self->fds[self->n_fds - 1].events;
00203 }
00204
00205 self->n_fds--;
00206 return;
00207 }
00208 }
00209 }
00210
00211 static void
00212 socket_set_poll_remove (DBusSocketSet *set,
00213 int fd)
00214 {
00215 DBusSocketSetPoll *self = socket_set_poll_cast (set);
00216
00217 socket_set_poll_disable (set, fd);
00218 self->n_reserved--;
00219
00220 _dbus_verbose ("after removing fd %d from %p, %d en/%d res/%d alloc\n",
00221 fd, self, self->n_fds, self->n_reserved, self->n_allocated);
00222 _dbus_assert (self->n_fds <= self->n_reserved);
00223 _dbus_assert (self->n_reserved <= self->n_allocated);
00224
00225 if (self->n_reserved + MINIMUM_SIZE < self->n_allocated / 2)
00226 {
00227
00228
00229 DBusPollFD *new_fds = dbus_realloc (self->fds,
00230 sizeof (DBusPollFD) * (self->n_reserved + MINIMUM_SIZE));
00231
00232 _dbus_verbose ("before deflating %p, %d en/%d res/%d alloc\n",
00233 self, self->n_fds, self->n_reserved, self->n_allocated);
00234
00235 if (_DBUS_UNLIKELY (new_fds == NULL))
00236 {
00237
00238 return;
00239 }
00240
00241 self->fds = new_fds;
00242 self->n_allocated = self->n_reserved;
00243 }
00244 }
00245
00246 static unsigned int
00247 watch_flags_from_poll_revents (short revents)
00248 {
00249 unsigned int condition = 0;
00250
00251 if (revents & _DBUS_POLLIN)
00252 condition |= DBUS_WATCH_READABLE;
00253 if (revents & _DBUS_POLLOUT)
00254 condition |= DBUS_WATCH_WRITABLE;
00255 if (revents & _DBUS_POLLHUP)
00256 condition |= DBUS_WATCH_HANGUP;
00257 if (revents & _DBUS_POLLERR)
00258 condition |= DBUS_WATCH_ERROR;
00259
00260 if (_DBUS_UNLIKELY (revents & _DBUS_POLLNVAL))
00261 condition |= _DBUS_WATCH_NVAL;
00262
00263 return condition;
00264 }
00265
00268 static int
00269 socket_set_poll_poll (DBusSocketSet *set,
00270 DBusSocketEvent *revents,
00271 int max_events,
00272 int timeout_ms)
00273 {
00274 DBusSocketSetPoll *self = socket_set_poll_cast (set);
00275 int i;
00276 int n_events;
00277 int n_ready;
00278
00279 _dbus_assert (max_events > 0);
00280
00281 for (i = 0; i < self->n_fds; i++)
00282 self->fds[i].revents = 0;
00283
00284 n_ready = _dbus_poll (self->fds, self->n_fds, timeout_ms);
00285
00286 if (n_ready <= 0)
00287 return n_ready;
00288
00289 n_events = 0;
00290
00291 for (i = 0; i < self->n_fds; i++)
00292 {
00293 if (self->fds[i].revents != 0)
00294 {
00295 revents[n_events].fd = self->fds[i].fd;
00296 revents[n_events].flags = watch_flags_from_poll_revents (self->fds[i].revents);
00297
00298 n_events += 1;
00299
00300
00301
00302
00303 if (n_events == max_events)
00304 return n_events;
00305 }
00306 }
00307
00308 return n_events;
00309 }
00310
00311 DBusSocketSetClass _dbus_socket_set_poll_class = {
00312 socket_set_poll_free,
00313 socket_set_poll_add,
00314 socket_set_poll_remove,
00315 socket_set_poll_enable,
00316 socket_set_poll_disable,
00317 socket_set_poll_poll
00318 };
00319
00320 #endif