diff options
| author | Paul Sokolovsky | 2015-12-05 14:53:53 +0200 |
|---|---|---|
| committer | Paul Sokolovsky | 2015-12-05 15:16:49 +0200 |
| commit | 082b12128d935eaf7ac49560c90734def1d0b232 (patch) | |
| tree | 2b15799a0ef1547035dadf80fdae0afde45368c5 | |
| parent | f2d532c4040ebf2aab96da1e8905433d140998e9 (diff) | |
unix/moduselect: register(): Allow to call with duplicate file descriptor.
Per CPython docs, "Registering a file descriptor that’s already registered
is not an error, and has the same effect as registering the descriptor
exactly once."
https://docs.python.org/3/library/select.html#select.poll.register
That's somewhat ambiguous, what's implemented here is that if fd si not
yet registered, it is registered. Otherwise, the effect is equivalent to
modify() method.
| -rw-r--r-- | unix/moduselect.c | 37 |
1 files changed, 21 insertions, 16 deletions
diff --git a/unix/moduselect.c b/unix/moduselect.c index 9abcc19dd..b86084b18 100644 --- a/unix/moduselect.c +++ b/unix/moduselect.c @@ -47,6 +47,7 @@ typedef struct _mp_obj_poll_t { /// \method register(obj[, eventmask]) STATIC mp_obj_t poll_register(uint n_args, const mp_obj_t *args) { mp_obj_poll_t *self = MP_OBJ_TO_PTR(args[0]); + int fd = mp_obj_get_int(args[1]); mp_uint_t flags; if (n_args == 3) { flags = mp_obj_get_int(args[2]); @@ -54,28 +55,32 @@ STATIC mp_obj_t poll_register(uint n_args, const mp_obj_t *args) { flags = POLLIN | POLLOUT; } - int i = 0; - if (self->len < self->alloc) { - i = self->len++; - } else { - struct pollfd *entries = self->entries; - for (i = 0; i < self->len; i++, entries++) { - if (entries->fd == -1) { - break; - } + struct pollfd *free_slot = NULL; + + struct pollfd *entry = self->entries; + for (int i = 0; i < self->len; i++, entry++) { + int entry_fd = entry->fd; + if (entry_fd == fd) { + entry->events = flags; + return mp_const_false; + } + if (entry_fd == -1) { + free_slot = entry; } - if (entries->fd != -1) { - i = self->len++; + } + + if (free_slot == NULL) { + if (self->len >= self->alloc) { self->entries = m_renew(struct pollfd, self->entries, self->alloc, self->alloc + 4); self->alloc += 4; } + free_slot = &self->entries[self->len++]; } - self->entries[i].fd = mp_obj_get_int(args[1]); - self->entries[i].events = flags; - self->entries[i].revents = 0; - - return mp_const_none; + free_slot->fd = fd; + free_slot->events = flags; + free_slot->revents = 0; + return mp_const_true; } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(poll_register_obj, 2, 3, poll_register); |
