Damien George | 6c9c7bc | 2014-08-21 15:12:51 +0100 | [diff] [blame] | 1 | /* |
Alexander Steffen | 55f3324 | 2017-06-30 09:22:17 +0200 | [diff] [blame^] | 2 | * This file is part of the MicroPython project, http://micropython.org/ |
Damien George | 6c9c7bc | 2014-08-21 15:12:51 +0100 | [diff] [blame] | 3 | * |
| 4 | * The MIT License (MIT) |
| 5 | * |
| 6 | * Copyright (c) 2014 Damien P. George |
| 7 | * |
| 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy |
| 9 | * of this software and associated documentation files (the "Software"), to deal |
| 10 | * in the Software without restriction, including without limitation the rights |
| 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
| 12 | * copies of the Software, and to permit persons to whom the Software is |
| 13 | * furnished to do so, subject to the following conditions: |
| 14 | * |
| 15 | * The above copyright notice and this permission notice shall be included in |
| 16 | * all copies or substantial portions of the Software. |
| 17 | * |
| 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
| 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
| 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
| 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
| 24 | * THE SOFTWARE. |
| 25 | */ |
| 26 | |
Paul Sokolovsky | 8f5bc3f | 2016-11-20 23:49:45 +0300 | [diff] [blame] | 27 | #include "py/mpconfig.h" |
| 28 | #if MICROPY_PY_USELECT |
| 29 | |
Damien George | 6c9c7bc | 2014-08-21 15:12:51 +0100 | [diff] [blame] | 30 | #include <stdio.h> |
| 31 | |
Damien George | a2bfcbe | 2016-10-07 13:58:25 +1100 | [diff] [blame] | 32 | #include "py/runtime.h" |
Damien George | 2cf6dfa | 2015-01-01 21:06:20 +0000 | [diff] [blame] | 33 | #include "py/obj.h" |
| 34 | #include "py/objlist.h" |
Damien George | 304cfda | 2016-12-02 16:37:29 +1100 | [diff] [blame] | 35 | #include "py/stream.h" |
Damien George | 5ab98d5 | 2016-05-10 23:22:54 +0100 | [diff] [blame] | 36 | #include "py/mperrno.h" |
Damien George | 731f359 | 2015-10-30 23:03:58 +0000 | [diff] [blame] | 37 | #include "py/mphal.h" |
Damien George | 6c9c7bc | 2014-08-21 15:12:51 +0100 | [diff] [blame] | 38 | |
Paul Sokolovsky | be3ae9d | 2015-12-13 21:05:17 +0200 | [diff] [blame] | 39 | // Flags for poll() |
| 40 | #define FLAG_ONESHOT (1) |
| 41 | |
Damien George | 013d53c | 2014-08-26 17:18:12 +0100 | [diff] [blame] | 42 | /// \module select - Provides select function to wait for events on a stream |
| 43 | /// |
| 44 | /// This module provides the select function. |
Damien George | 6c9c7bc | 2014-08-21 15:12:51 +0100 | [diff] [blame] | 45 | |
Damien George | 6c9c7bc | 2014-08-21 15:12:51 +0100 | [diff] [blame] | 46 | typedef struct _poll_obj_t { |
Damien George | e2a6186 | 2014-08-22 21:49:08 +0100 | [diff] [blame] | 47 | mp_obj_t obj; |
Paul Sokolovsky | f4a6a57 | 2014-11-17 00:16:14 +0200 | [diff] [blame] | 48 | mp_uint_t (*ioctl)(mp_obj_t obj, mp_uint_t request, mp_uint_t arg, int *errcode); |
Damien George | 6c9c7bc | 2014-08-21 15:12:51 +0100 | [diff] [blame] | 49 | mp_uint_t flags; |
| 50 | mp_uint_t flags_ret; |
| 51 | } poll_obj_t; |
| 52 | |
| 53 | STATIC void poll_map_add(mp_map_t *poll_map, const mp_obj_t *obj, mp_uint_t obj_len, mp_uint_t flags, bool or_flags) { |
| 54 | for (mp_uint_t i = 0; i < obj_len; i++) { |
Damien George | e2a6186 | 2014-08-22 21:49:08 +0100 | [diff] [blame] | 55 | mp_map_elem_t *elem = mp_map_lookup(poll_map, mp_obj_id(obj[i]), MP_MAP_LOOKUP_ADD_IF_NOT_FOUND); |
Damien George | 6c9c7bc | 2014-08-21 15:12:51 +0100 | [diff] [blame] | 56 | if (elem->value == NULL) { |
| 57 | // object not found; get its ioctl and add it to the poll list |
Damien George | ebc8d73 | 2016-12-02 16:39:50 +1100 | [diff] [blame] | 58 | const mp_stream_p_t *stream_p = mp_get_stream_raise(obj[i], MP_STREAM_OP_IOCTL); |
Damien George | 6c9c7bc | 2014-08-21 15:12:51 +0100 | [diff] [blame] | 59 | poll_obj_t *poll_obj = m_new_obj(poll_obj_t); |
Damien George | e2a6186 | 2014-08-22 21:49:08 +0100 | [diff] [blame] | 60 | poll_obj->obj = obj[i]; |
Paul Sokolovsky | 07209f8 | 2016-06-18 18:19:24 +0300 | [diff] [blame] | 61 | poll_obj->ioctl = stream_p->ioctl; |
Damien George | 6c9c7bc | 2014-08-21 15:12:51 +0100 | [diff] [blame] | 62 | poll_obj->flags = flags; |
| 63 | poll_obj->flags_ret = 0; |
| 64 | elem->value = poll_obj; |
| 65 | } else { |
| 66 | // object exists; update its flags |
| 67 | if (or_flags) { |
| 68 | ((poll_obj_t*)elem->value)->flags |= flags; |
| 69 | } else { |
| 70 | ((poll_obj_t*)elem->value)->flags = flags; |
| 71 | } |
| 72 | } |
| 73 | } |
| 74 | } |
| 75 | |
| 76 | // poll each object in the map |
| 77 | STATIC mp_uint_t poll_map_poll(mp_map_t *poll_map, mp_uint_t *rwx_num) { |
| 78 | mp_uint_t n_ready = 0; |
| 79 | for (mp_uint_t i = 0; i < poll_map->alloc; ++i) { |
| 80 | if (!MP_MAP_SLOT_IS_FILLED(poll_map, i)) { |
| 81 | continue; |
| 82 | } |
| 83 | |
| 84 | poll_obj_t *poll_obj = (poll_obj_t*)poll_map->table[i].value; |
Damien George | a2f55fe | 2014-08-21 22:48:23 +0100 | [diff] [blame] | 85 | int errcode; |
Damien George | 304cfda | 2016-12-02 16:37:29 +1100 | [diff] [blame] | 86 | mp_int_t ret = poll_obj->ioctl(poll_obj->obj, MP_STREAM_POLL, poll_obj->flags, &errcode); |
Damien George | 6c9c7bc | 2014-08-21 15:12:51 +0100 | [diff] [blame] | 87 | poll_obj->flags_ret = ret; |
| 88 | |
| 89 | if (ret == -1) { |
| 90 | // error doing ioctl |
Damien George | a2bfcbe | 2016-10-07 13:58:25 +1100 | [diff] [blame] | 91 | mp_raise_OSError(errcode); |
Damien George | 6c9c7bc | 2014-08-21 15:12:51 +0100 | [diff] [blame] | 92 | } |
| 93 | |
| 94 | if (ret != 0) { |
| 95 | // object is ready |
| 96 | n_ready += 1; |
| 97 | if (rwx_num != NULL) { |
Damien George | 304cfda | 2016-12-02 16:37:29 +1100 | [diff] [blame] | 98 | if (ret & MP_STREAM_POLL_RD) { |
Damien George | 6c9c7bc | 2014-08-21 15:12:51 +0100 | [diff] [blame] | 99 | rwx_num[0] += 1; |
| 100 | } |
Damien George | 304cfda | 2016-12-02 16:37:29 +1100 | [diff] [blame] | 101 | if (ret & MP_STREAM_POLL_WR) { |
Damien George | 6c9c7bc | 2014-08-21 15:12:51 +0100 | [diff] [blame] | 102 | rwx_num[1] += 1; |
| 103 | } |
Damien George | 304cfda | 2016-12-02 16:37:29 +1100 | [diff] [blame] | 104 | if ((ret & ~(MP_STREAM_POLL_RD | MP_STREAM_POLL_WR)) != 0) { |
Damien George | 6c9c7bc | 2014-08-21 15:12:51 +0100 | [diff] [blame] | 105 | rwx_num[2] += 1; |
| 106 | } |
| 107 | } |
| 108 | } |
| 109 | } |
| 110 | return n_ready; |
| 111 | } |
| 112 | |
| 113 | /// \function select(rlist, wlist, xlist[, timeout]) |
| 114 | STATIC mp_obj_t select_select(uint n_args, const mp_obj_t *args) { |
| 115 | // get array data from tuple/list arguments |
Damien George | a8a3ab4 | 2017-03-26 17:19:08 +1100 | [diff] [blame] | 116 | size_t rwx_len[3]; |
Damien George | 6c9c7bc | 2014-08-21 15:12:51 +0100 | [diff] [blame] | 117 | mp_obj_t *r_array, *w_array, *x_array; |
| 118 | mp_obj_get_array(args[0], &rwx_len[0], &r_array); |
| 119 | mp_obj_get_array(args[1], &rwx_len[1], &w_array); |
| 120 | mp_obj_get_array(args[2], &rwx_len[2], &x_array); |
| 121 | |
| 122 | // get timeout |
| 123 | mp_uint_t timeout = -1; |
| 124 | if (n_args == 4) { |
| 125 | if (args[3] != mp_const_none) { |
Dave Hylands | 39296b4 | 2014-09-26 09:04:05 -0700 | [diff] [blame] | 126 | #if MICROPY_PY_BUILTINS_FLOAT |
Damien George | 6c9c7bc | 2014-08-21 15:12:51 +0100 | [diff] [blame] | 127 | float timeout_f = mp_obj_get_float(args[3]); |
| 128 | if (timeout_f >= 0) { |
| 129 | timeout = (mp_uint_t)(timeout_f * 1000); |
| 130 | } |
Dave Hylands | 39296b4 | 2014-09-26 09:04:05 -0700 | [diff] [blame] | 131 | #else |
| 132 | timeout = mp_obj_get_int(args[3]) * 1000; |
| 133 | #endif |
Damien George | 6c9c7bc | 2014-08-21 15:12:51 +0100 | [diff] [blame] | 134 | } |
| 135 | } |
| 136 | |
| 137 | // merge separate lists and get the ioctl function for each object |
| 138 | mp_map_t poll_map; |
| 139 | mp_map_init(&poll_map, rwx_len[0] + rwx_len[1] + rwx_len[2]); |
Damien George | 304cfda | 2016-12-02 16:37:29 +1100 | [diff] [blame] | 140 | poll_map_add(&poll_map, r_array, rwx_len[0], MP_STREAM_POLL_RD, true); |
| 141 | poll_map_add(&poll_map, w_array, rwx_len[1], MP_STREAM_POLL_WR, true); |
| 142 | poll_map_add(&poll_map, x_array, rwx_len[2], MP_STREAM_POLL_ERR | MP_STREAM_POLL_HUP, true); |
Damien George | 6c9c7bc | 2014-08-21 15:12:51 +0100 | [diff] [blame] | 143 | |
Paul Sokolovsky | 19b671c | 2015-10-29 20:42:12 +0300 | [diff] [blame] | 144 | mp_uint_t start_tick = mp_hal_ticks_ms(); |
Damien George | 6c9c7bc | 2014-08-21 15:12:51 +0100 | [diff] [blame] | 145 | rwx_len[0] = rwx_len[1] = rwx_len[2] = 0; |
| 146 | for (;;) { |
| 147 | // poll the objects |
| 148 | mp_uint_t n_ready = poll_map_poll(&poll_map, rwx_len); |
| 149 | |
Paul Sokolovsky | 19b671c | 2015-10-29 20:42:12 +0300 | [diff] [blame] | 150 | if (n_ready > 0 || (timeout != -1 && mp_hal_ticks_ms() - start_tick >= timeout)) { |
Damien George | 6c9c7bc | 2014-08-21 15:12:51 +0100 | [diff] [blame] | 151 | // one or more objects are ready, or we had a timeout |
| 152 | mp_obj_t list_array[3]; |
| 153 | list_array[0] = mp_obj_new_list(rwx_len[0], NULL); |
| 154 | list_array[1] = mp_obj_new_list(rwx_len[1], NULL); |
| 155 | list_array[2] = mp_obj_new_list(rwx_len[2], NULL); |
| 156 | rwx_len[0] = rwx_len[1] = rwx_len[2] = 0; |
| 157 | for (mp_uint_t i = 0; i < poll_map.alloc; ++i) { |
| 158 | if (!MP_MAP_SLOT_IS_FILLED(&poll_map, i)) { |
| 159 | continue; |
| 160 | } |
| 161 | poll_obj_t *poll_obj = (poll_obj_t*)poll_map.table[i].value; |
Damien George | 304cfda | 2016-12-02 16:37:29 +1100 | [diff] [blame] | 162 | if (poll_obj->flags_ret & MP_STREAM_POLL_RD) { |
Damien George | e2a6186 | 2014-08-22 21:49:08 +0100 | [diff] [blame] | 163 | ((mp_obj_list_t*)list_array[0])->items[rwx_len[0]++] = poll_obj->obj; |
Damien George | 6c9c7bc | 2014-08-21 15:12:51 +0100 | [diff] [blame] | 164 | } |
Damien George | 304cfda | 2016-12-02 16:37:29 +1100 | [diff] [blame] | 165 | if (poll_obj->flags_ret & MP_STREAM_POLL_WR) { |
Damien George | e2a6186 | 2014-08-22 21:49:08 +0100 | [diff] [blame] | 166 | ((mp_obj_list_t*)list_array[1])->items[rwx_len[1]++] = poll_obj->obj; |
Damien George | 6c9c7bc | 2014-08-21 15:12:51 +0100 | [diff] [blame] | 167 | } |
Damien George | 304cfda | 2016-12-02 16:37:29 +1100 | [diff] [blame] | 168 | if ((poll_obj->flags_ret & ~(MP_STREAM_POLL_RD | MP_STREAM_POLL_WR)) != 0) { |
Damien George | e2a6186 | 2014-08-22 21:49:08 +0100 | [diff] [blame] | 169 | ((mp_obj_list_t*)list_array[2])->items[rwx_len[2]++] = poll_obj->obj; |
Damien George | 6c9c7bc | 2014-08-21 15:12:51 +0100 | [diff] [blame] | 170 | } |
| 171 | } |
| 172 | mp_map_deinit(&poll_map); |
| 173 | return mp_obj_new_tuple(3, list_array); |
| 174 | } |
Damien George | 2d329c4 | 2016-12-02 16:40:39 +1100 | [diff] [blame] | 175 | MICROPY_EVENT_POLL_HOOK |
Damien George | 6c9c7bc | 2014-08-21 15:12:51 +0100 | [diff] [blame] | 176 | } |
| 177 | } |
| 178 | MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_select_select_obj, 3, 4, select_select); |
| 179 | |
Damien George | 2842945 | 2014-09-17 23:27:42 +0000 | [diff] [blame] | 180 | /// \class Poll - poll class |
Damien George | 6c9c7bc | 2014-08-21 15:12:51 +0100 | [diff] [blame] | 181 | |
| 182 | typedef struct _mp_obj_poll_t { |
| 183 | mp_obj_base_t base; |
| 184 | mp_map_t poll_map; |
Paul Sokolovsky | de3a96b | 2017-04-29 13:05:44 +0300 | [diff] [blame] | 185 | short iter_cnt; |
| 186 | short iter_idx; |
Paul Sokolovsky | edc0dcb | 2017-04-29 13:05:20 +0300 | [diff] [blame] | 187 | int flags; |
Paul Sokolovsky | de3a96b | 2017-04-29 13:05:44 +0300 | [diff] [blame] | 188 | // callee-owned tuple |
| 189 | mp_obj_t ret_tuple; |
Damien George | 6c9c7bc | 2014-08-21 15:12:51 +0100 | [diff] [blame] | 190 | } mp_obj_poll_t; |
| 191 | |
| 192 | /// \method register(obj[, eventmask]) |
| 193 | STATIC mp_obj_t poll_register(uint n_args, const mp_obj_t *args) { |
| 194 | mp_obj_poll_t *self = args[0]; |
| 195 | mp_uint_t flags; |
| 196 | if (n_args == 3) { |
| 197 | flags = mp_obj_get_int(args[2]); |
| 198 | } else { |
Damien George | 304cfda | 2016-12-02 16:37:29 +1100 | [diff] [blame] | 199 | flags = MP_STREAM_POLL_RD | MP_STREAM_POLL_WR; |
Damien George | 6c9c7bc | 2014-08-21 15:12:51 +0100 | [diff] [blame] | 200 | } |
| 201 | poll_map_add(&self->poll_map, &args[1], 1, flags, false); |
| 202 | return mp_const_none; |
| 203 | } |
| 204 | MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(poll_register_obj, 2, 3, poll_register); |
| 205 | |
| 206 | /// \method unregister(obj) |
| 207 | STATIC mp_obj_t poll_unregister(mp_obj_t self_in, mp_obj_t obj_in) { |
| 208 | mp_obj_poll_t *self = self_in; |
Damien George | e2a6186 | 2014-08-22 21:49:08 +0100 | [diff] [blame] | 209 | mp_map_lookup(&self->poll_map, mp_obj_id(obj_in), MP_MAP_LOOKUP_REMOVE_IF_FOUND); |
Damien George | 6c9c7bc | 2014-08-21 15:12:51 +0100 | [diff] [blame] | 210 | // TODO raise KeyError if obj didn't exist in map |
| 211 | return mp_const_none; |
| 212 | } |
| 213 | MP_DEFINE_CONST_FUN_OBJ_2(poll_unregister_obj, poll_unregister); |
| 214 | |
| 215 | /// \method modify(obj, eventmask) |
| 216 | STATIC mp_obj_t poll_modify(mp_obj_t self_in, mp_obj_t obj_in, mp_obj_t eventmask_in) { |
| 217 | mp_obj_poll_t *self = self_in; |
Damien George | e2a6186 | 2014-08-22 21:49:08 +0100 | [diff] [blame] | 218 | mp_map_elem_t *elem = mp_map_lookup(&self->poll_map, mp_obj_id(obj_in), MP_MAP_LOOKUP); |
Damien George | 6c9c7bc | 2014-08-21 15:12:51 +0100 | [diff] [blame] | 219 | if (elem == NULL) { |
Damien George | a2bfcbe | 2016-10-07 13:58:25 +1100 | [diff] [blame] | 220 | mp_raise_OSError(MP_ENOENT); |
Damien George | 6c9c7bc | 2014-08-21 15:12:51 +0100 | [diff] [blame] | 221 | } |
| 222 | ((poll_obj_t*)elem->value)->flags = mp_obj_get_int(eventmask_in); |
| 223 | return mp_const_none; |
| 224 | } |
| 225 | MP_DEFINE_CONST_FUN_OBJ_3(poll_modify_obj, poll_modify); |
| 226 | |
Paul Sokolovsky | edc0dcb | 2017-04-29 13:05:20 +0300 | [diff] [blame] | 227 | STATIC mp_uint_t poll_poll_internal(uint n_args, const mp_obj_t *args) { |
Damien George | 6c9c7bc | 2014-08-21 15:12:51 +0100 | [diff] [blame] | 228 | mp_obj_poll_t *self = args[0]; |
| 229 | |
| 230 | // work out timeout (its given already in ms) |
| 231 | mp_uint_t timeout = -1; |
Paul Sokolovsky | be3ae9d | 2015-12-13 21:05:17 +0200 | [diff] [blame] | 232 | int flags = 0; |
| 233 | if (n_args >= 2) { |
Damien George | 6c9c7bc | 2014-08-21 15:12:51 +0100 | [diff] [blame] | 234 | if (args[1] != mp_const_none) { |
| 235 | mp_int_t timeout_i = mp_obj_get_int(args[1]); |
| 236 | if (timeout_i >= 0) { |
| 237 | timeout = timeout_i; |
| 238 | } |
| 239 | } |
Paul Sokolovsky | be3ae9d | 2015-12-13 21:05:17 +0200 | [diff] [blame] | 240 | if (n_args >= 3) { |
| 241 | flags = mp_obj_get_int(args[2]); |
| 242 | } |
Damien George | 6c9c7bc | 2014-08-21 15:12:51 +0100 | [diff] [blame] | 243 | } |
| 244 | |
Paul Sokolovsky | edc0dcb | 2017-04-29 13:05:20 +0300 | [diff] [blame] | 245 | self->flags = flags; |
| 246 | |
Paul Sokolovsky | 19b671c | 2015-10-29 20:42:12 +0300 | [diff] [blame] | 247 | mp_uint_t start_tick = mp_hal_ticks_ms(); |
Paul Sokolovsky | edc0dcb | 2017-04-29 13:05:20 +0300 | [diff] [blame] | 248 | mp_uint_t n_ready; |
Damien George | 6c9c7bc | 2014-08-21 15:12:51 +0100 | [diff] [blame] | 249 | for (;;) { |
| 250 | // poll the objects |
Paul Sokolovsky | edc0dcb | 2017-04-29 13:05:20 +0300 | [diff] [blame] | 251 | n_ready = poll_map_poll(&self->poll_map, NULL); |
Paul Sokolovsky | 19b671c | 2015-10-29 20:42:12 +0300 | [diff] [blame] | 252 | if (n_ready > 0 || (timeout != -1 && mp_hal_ticks_ms() - start_tick >= timeout)) { |
Paul Sokolovsky | edc0dcb | 2017-04-29 13:05:20 +0300 | [diff] [blame] | 253 | break; |
Damien George | 6c9c7bc | 2014-08-21 15:12:51 +0100 | [diff] [blame] | 254 | } |
Damien George | 2d329c4 | 2016-12-02 16:40:39 +1100 | [diff] [blame] | 255 | MICROPY_EVENT_POLL_HOOK |
Damien George | 6c9c7bc | 2014-08-21 15:12:51 +0100 | [diff] [blame] | 256 | } |
Paul Sokolovsky | edc0dcb | 2017-04-29 13:05:20 +0300 | [diff] [blame] | 257 | |
| 258 | return n_ready; |
| 259 | } |
| 260 | |
| 261 | STATIC mp_obj_t poll_poll(uint n_args, const mp_obj_t *args) { |
| 262 | mp_obj_poll_t *self = args[0]; |
| 263 | mp_uint_t n_ready = poll_poll_internal(n_args, args); |
| 264 | |
| 265 | // one or more objects are ready, or we had a timeout |
| 266 | mp_obj_list_t *ret_list = mp_obj_new_list(n_ready, NULL); |
| 267 | n_ready = 0; |
| 268 | for (mp_uint_t i = 0; i < self->poll_map.alloc; ++i) { |
| 269 | if (!MP_MAP_SLOT_IS_FILLED(&self->poll_map, i)) { |
| 270 | continue; |
| 271 | } |
| 272 | poll_obj_t *poll_obj = (poll_obj_t*)self->poll_map.table[i].value; |
| 273 | if (poll_obj->flags_ret != 0) { |
| 274 | mp_obj_t tuple[2] = {poll_obj->obj, MP_OBJ_NEW_SMALL_INT(poll_obj->flags_ret)}; |
| 275 | ret_list->items[n_ready++] = mp_obj_new_tuple(2, tuple); |
| 276 | if (self->flags & FLAG_ONESHOT) { |
| 277 | // Don't poll next time, until new event flags will be set explicitly |
| 278 | poll_obj->flags = 0; |
| 279 | } |
| 280 | } |
| 281 | } |
| 282 | return ret_list; |
Damien George | 6c9c7bc | 2014-08-21 15:12:51 +0100 | [diff] [blame] | 283 | } |
Paul Sokolovsky | be3ae9d | 2015-12-13 21:05:17 +0200 | [diff] [blame] | 284 | MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(poll_poll_obj, 1, 3, poll_poll); |
Damien George | 6c9c7bc | 2014-08-21 15:12:51 +0100 | [diff] [blame] | 285 | |
Paul Sokolovsky | de3a96b | 2017-04-29 13:05:44 +0300 | [diff] [blame] | 286 | STATIC mp_obj_t poll_ipoll(size_t n_args, const mp_obj_t *args) { |
| 287 | mp_obj_poll_t *self = MP_OBJ_TO_PTR(args[0]); |
| 288 | |
| 289 | if (self->ret_tuple == MP_OBJ_NULL) { |
| 290 | self->ret_tuple = mp_obj_new_tuple(2, NULL); |
| 291 | } |
| 292 | |
| 293 | int n_ready = poll_poll_internal(n_args, args); |
| 294 | self->iter_cnt = n_ready; |
| 295 | self->iter_idx = 0; |
| 296 | |
| 297 | return args[0]; |
| 298 | } |
| 299 | MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(poll_ipoll_obj, 1, 3, poll_ipoll); |
| 300 | |
| 301 | STATIC mp_obj_t poll_iternext(mp_obj_t self_in) { |
| 302 | mp_obj_poll_t *self = MP_OBJ_TO_PTR(self_in); |
| 303 | |
| 304 | if (self->iter_cnt == 0) { |
| 305 | return MP_OBJ_STOP_ITERATION; |
| 306 | } |
| 307 | |
| 308 | self->iter_cnt--; |
| 309 | |
| 310 | for (mp_uint_t i = self->iter_idx; i < self->poll_map.alloc; ++i) { |
| 311 | self->iter_idx++; |
| 312 | if (!MP_MAP_SLOT_IS_FILLED(&self->poll_map, i)) { |
| 313 | continue; |
| 314 | } |
| 315 | poll_obj_t *poll_obj = (poll_obj_t*)self->poll_map.table[i].value; |
| 316 | if (poll_obj->flags_ret != 0) { |
| 317 | mp_obj_tuple_t *t = MP_OBJ_TO_PTR(self->ret_tuple); |
| 318 | t->items[0] = poll_obj->obj; |
| 319 | t->items[1] = MP_OBJ_NEW_SMALL_INT(poll_obj->flags_ret); |
| 320 | if (self->flags & FLAG_ONESHOT) { |
| 321 | // Don't poll next time, until new event flags will be set explicitly |
| 322 | poll_obj->flags = 0; |
| 323 | } |
| 324 | return MP_OBJ_FROM_PTR(t); |
| 325 | } |
| 326 | } |
| 327 | |
| 328 | assert(!"inconsistent number of poll active entries"); |
| 329 | self->iter_cnt = 0; |
| 330 | return MP_OBJ_STOP_ITERATION; |
| 331 | } |
| 332 | |
Paul Sokolovsky | b082869 | 2017-04-29 11:03:46 +0300 | [diff] [blame] | 333 | STATIC const mp_rom_map_elem_t poll_locals_dict_table[] = { |
| 334 | { MP_ROM_QSTR(MP_QSTR_register), MP_ROM_PTR(&poll_register_obj) }, |
| 335 | { MP_ROM_QSTR(MP_QSTR_unregister), MP_ROM_PTR(&poll_unregister_obj) }, |
| 336 | { MP_ROM_QSTR(MP_QSTR_modify), MP_ROM_PTR(&poll_modify_obj) }, |
| 337 | { MP_ROM_QSTR(MP_QSTR_poll), MP_ROM_PTR(&poll_poll_obj) }, |
Paul Sokolovsky | de3a96b | 2017-04-29 13:05:44 +0300 | [diff] [blame] | 338 | { MP_ROM_QSTR(MP_QSTR_ipoll), MP_ROM_PTR(&poll_ipoll_obj) }, |
Damien George | 6c9c7bc | 2014-08-21 15:12:51 +0100 | [diff] [blame] | 339 | }; |
| 340 | STATIC MP_DEFINE_CONST_DICT(poll_locals_dict, poll_locals_dict_table); |
| 341 | |
| 342 | STATIC const mp_obj_type_t mp_type_poll = { |
| 343 | { &mp_type_type }, |
| 344 | .name = MP_QSTR_poll, |
Paul Sokolovsky | de3a96b | 2017-04-29 13:05:44 +0300 | [diff] [blame] | 345 | .getiter = mp_identity_getiter, |
| 346 | .iternext = poll_iternext, |
Paul Sokolovsky | b082869 | 2017-04-29 11:03:46 +0300 | [diff] [blame] | 347 | .locals_dict = (void*)&poll_locals_dict, |
Damien George | 6c9c7bc | 2014-08-21 15:12:51 +0100 | [diff] [blame] | 348 | }; |
| 349 | |
| 350 | /// \function poll() |
| 351 | STATIC mp_obj_t select_poll(void) { |
| 352 | mp_obj_poll_t *poll = m_new_obj(mp_obj_poll_t); |
| 353 | poll->base.type = &mp_type_poll; |
| 354 | mp_map_init(&poll->poll_map, 0); |
Paul Sokolovsky | de3a96b | 2017-04-29 13:05:44 +0300 | [diff] [blame] | 355 | poll->iter_cnt = 0; |
| 356 | poll->ret_tuple = MP_OBJ_NULL; |
Damien George | 6c9c7bc | 2014-08-21 15:12:51 +0100 | [diff] [blame] | 357 | return poll; |
| 358 | } |
| 359 | MP_DEFINE_CONST_FUN_OBJ_0(mp_select_poll_obj, select_poll); |
Damien George | 013d53c | 2014-08-26 17:18:12 +0100 | [diff] [blame] | 360 | |
Paul Sokolovsky | b082869 | 2017-04-29 11:03:46 +0300 | [diff] [blame] | 361 | STATIC const mp_rom_map_elem_t mp_module_select_globals_table[] = { |
| 362 | { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_uselect) }, |
| 363 | { MP_ROM_QSTR(MP_QSTR_select), MP_ROM_PTR(&mp_select_select_obj) }, |
| 364 | { MP_ROM_QSTR(MP_QSTR_poll), MP_ROM_PTR(&mp_select_poll_obj) }, |
Damien George | bbced3b | 2017-07-31 13:00:34 +1000 | [diff] [blame] | 365 | { MP_ROM_QSTR(MP_QSTR_POLLIN), MP_ROM_INT(MP_STREAM_POLL_RD) }, |
| 366 | { MP_ROM_QSTR(MP_QSTR_POLLOUT), MP_ROM_INT(MP_STREAM_POLL_WR) }, |
| 367 | { MP_ROM_QSTR(MP_QSTR_POLLERR), MP_ROM_INT(MP_STREAM_POLL_ERR) }, |
| 368 | { MP_ROM_QSTR(MP_QSTR_POLLHUP), MP_ROM_INT(MP_STREAM_POLL_HUP) }, |
Damien George | 013d53c | 2014-08-26 17:18:12 +0100 | [diff] [blame] | 369 | }; |
| 370 | |
Damien George | 3b603f2 | 2014-11-29 14:39:27 +0000 | [diff] [blame] | 371 | STATIC MP_DEFINE_CONST_DICT(mp_module_select_globals, mp_module_select_globals_table); |
Damien George | 013d53c | 2014-08-26 17:18:12 +0100 | [diff] [blame] | 372 | |
Damien George | 0107e90 | 2014-10-12 20:23:47 +0100 | [diff] [blame] | 373 | const mp_obj_module_t mp_module_uselect = { |
Damien George | 013d53c | 2014-08-26 17:18:12 +0100 | [diff] [blame] | 374 | .base = { &mp_type_module }, |
Damien George | 013d53c | 2014-08-26 17:18:12 +0100 | [diff] [blame] | 375 | .globals = (mp_obj_dict_t*)&mp_module_select_globals, |
| 376 | }; |
Paul Sokolovsky | 8f5bc3f | 2016-11-20 23:49:45 +0300 | [diff] [blame] | 377 | |
Damien George | 0d56c65 | 2016-11-21 15:47:48 +1100 | [diff] [blame] | 378 | #endif // MICROPY_PY_USELECT |