extmod/modtimeq: Remove timeq module.
This is a MicroPython-specific module that existed to support the old version of uasyncio. It's undocumented and not enabled on all ports and takes up code size unnecessarily. Signed-off-by: Jim Mussared <jim.mussared@gmail.com>
This commit is contained in:
parent
8211d56712
commit
a1fbb1980c
|
@ -34,7 +34,6 @@ set(MICROPY_SOURCE_EXTMOD
|
|||
${MICROPY_EXTMOD_DIR}/modssl_axtls.c
|
||||
${MICROPY_EXTMOD_DIR}/modssl_mbedtls.c
|
||||
${MICROPY_EXTMOD_DIR}/modtime.c
|
||||
${MICROPY_EXTMOD_DIR}/modtimeq.c
|
||||
${MICROPY_EXTMOD_DIR}/modwebsocket.c
|
||||
${MICROPY_EXTMOD_DIR}/modzlib.c
|
||||
${MICROPY_EXTMOD_DIR}/modwebrepl.c
|
||||
|
|
|
@ -31,7 +31,6 @@ SRC_EXTMOD_C += \
|
|||
extmod/modssl_axtls.c \
|
||||
extmod/modssl_mbedtls.c \
|
||||
extmod/modtime.c \
|
||||
extmod/modtimeq.c \
|
||||
extmod/moduasyncio.c \
|
||||
extmod/moductypes.c \
|
||||
extmod/modwebrepl.c \
|
||||
|
|
|
@ -1,235 +0,0 @@
|
|||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2014 Damien P. George
|
||||
* Copyright (c) 2016-2017 Paul Sokolovsky
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "py/objlist.h"
|
||||
#include "py/runtime.h"
|
||||
#include "py/smallint.h"
|
||||
|
||||
#if MICROPY_PY_TIMEQ
|
||||
|
||||
#define MODULO MICROPY_PY_TIME_TICKS_PERIOD
|
||||
|
||||
#define DEBUG 0
|
||||
|
||||
// the algorithm here is modelled on CPython's heapq.py
|
||||
|
||||
struct qentry {
|
||||
mp_uint_t time;
|
||||
mp_uint_t id;
|
||||
mp_obj_t callback;
|
||||
mp_obj_t args;
|
||||
};
|
||||
|
||||
typedef struct _mp_obj_timeq_t {
|
||||
mp_obj_base_t base;
|
||||
mp_uint_t alloc;
|
||||
mp_uint_t len;
|
||||
struct qentry items[];
|
||||
} mp_obj_timeq_t;
|
||||
|
||||
STATIC mp_uint_t timeq_id;
|
||||
|
||||
STATIC mp_obj_timeq_t *timeq_get_heap(mp_obj_t heap_in) {
|
||||
return MP_OBJ_TO_PTR(heap_in);
|
||||
}
|
||||
|
||||
STATIC bool time_less_than(struct qentry *item, struct qentry *parent) {
|
||||
mp_uint_t item_tm = item->time;
|
||||
mp_uint_t parent_tm = parent->time;
|
||||
mp_uint_t res = parent_tm - item_tm;
|
||||
if (res == 0) {
|
||||
// TODO: This actually should use the same "ring" logic
|
||||
// as for time, to avoid artifacts when id's overflow.
|
||||
return item->id < parent->id;
|
||||
}
|
||||
if ((mp_int_t)res < 0) {
|
||||
res += MODULO;
|
||||
}
|
||||
return res && res < (MODULO / 2);
|
||||
}
|
||||
|
||||
STATIC mp_obj_t timeq_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
|
||||
mp_arg_check_num(n_args, n_kw, 1, 1, false);
|
||||
mp_uint_t alloc = mp_obj_get_int(args[0]);
|
||||
mp_obj_timeq_t *o = mp_obj_malloc_var(mp_obj_timeq_t, struct qentry, alloc, type);
|
||||
memset(o->items, 0, sizeof(*o->items) * alloc);
|
||||
o->alloc = alloc;
|
||||
o->len = 0;
|
||||
return MP_OBJ_FROM_PTR(o);
|
||||
}
|
||||
|
||||
STATIC void timeq_heap_siftdown(mp_obj_timeq_t *heap, mp_uint_t start_pos, mp_uint_t pos) {
|
||||
struct qentry item = heap->items[pos];
|
||||
while (pos > start_pos) {
|
||||
mp_uint_t parent_pos = (pos - 1) >> 1;
|
||||
struct qentry *parent = &heap->items[parent_pos];
|
||||
bool lessthan = time_less_than(&item, parent);
|
||||
if (lessthan) {
|
||||
heap->items[pos] = *parent;
|
||||
pos = parent_pos;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
heap->items[pos] = item;
|
||||
}
|
||||
|
||||
STATIC void timeq_heap_siftup(mp_obj_timeq_t *heap, mp_uint_t pos) {
|
||||
mp_uint_t start_pos = pos;
|
||||
mp_uint_t end_pos = heap->len;
|
||||
struct qentry item = heap->items[pos];
|
||||
for (mp_uint_t child_pos = 2 * pos + 1; child_pos < end_pos; child_pos = 2 * pos + 1) {
|
||||
// choose right child if it's <= left child
|
||||
if (child_pos + 1 < end_pos) {
|
||||
bool lessthan = time_less_than(&heap->items[child_pos], &heap->items[child_pos + 1]);
|
||||
if (!lessthan) {
|
||||
child_pos += 1;
|
||||
}
|
||||
}
|
||||
// bubble up the smaller child
|
||||
heap->items[pos] = heap->items[child_pos];
|
||||
pos = child_pos;
|
||||
}
|
||||
heap->items[pos] = item;
|
||||
timeq_heap_siftdown(heap, start_pos, pos);
|
||||
}
|
||||
|
||||
STATIC mp_obj_t mod_timeq_heappush(size_t n_args, const mp_obj_t *args) {
|
||||
(void)n_args;
|
||||
mp_obj_t heap_in = args[0];
|
||||
mp_obj_timeq_t *heap = timeq_get_heap(heap_in);
|
||||
if (heap->len == heap->alloc) {
|
||||
mp_raise_msg(&mp_type_IndexError, MP_ERROR_TEXT("queue overflow"));
|
||||
}
|
||||
mp_uint_t l = heap->len;
|
||||
heap->items[l].time = MP_OBJ_SMALL_INT_VALUE(args[1]);
|
||||
heap->items[l].id = timeq_id++;
|
||||
heap->items[l].callback = args[2];
|
||||
heap->items[l].args = args[3];
|
||||
timeq_heap_siftdown(heap, 0, heap->len);
|
||||
heap->len++;
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_timeq_heappush_obj, 4, 4, mod_timeq_heappush);
|
||||
|
||||
STATIC mp_obj_t mod_timeq_heappop(mp_obj_t heap_in, mp_obj_t list_ref) {
|
||||
mp_obj_timeq_t *heap = timeq_get_heap(heap_in);
|
||||
if (heap->len == 0) {
|
||||
mp_raise_msg(&mp_type_IndexError, MP_ERROR_TEXT("empty heap"));
|
||||
}
|
||||
mp_obj_list_t *ret = MP_OBJ_TO_PTR(list_ref);
|
||||
if (!mp_obj_is_type(list_ref, &mp_type_list) || ret->len < 3) {
|
||||
mp_raise_TypeError(NULL);
|
||||
}
|
||||
|
||||
struct qentry *item = &heap->items[0];
|
||||
ret->items[0] = MP_OBJ_NEW_SMALL_INT(item->time);
|
||||
ret->items[1] = item->callback;
|
||||
ret->items[2] = item->args;
|
||||
heap->len -= 1;
|
||||
heap->items[0] = heap->items[heap->len];
|
||||
heap->items[heap->len].callback = MP_OBJ_NULL; // so we don't retain a pointer
|
||||
heap->items[heap->len].args = MP_OBJ_NULL;
|
||||
if (heap->len) {
|
||||
timeq_heap_siftup(heap, 0);
|
||||
}
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_timeq_heappop_obj, mod_timeq_heappop);
|
||||
|
||||
STATIC mp_obj_t mod_timeq_peektime(mp_obj_t heap_in) {
|
||||
mp_obj_timeq_t *heap = timeq_get_heap(heap_in);
|
||||
if (heap->len == 0) {
|
||||
mp_raise_msg(&mp_type_IndexError, MP_ERROR_TEXT("empty heap"));
|
||||
}
|
||||
|
||||
struct qentry *item = &heap->items[0];
|
||||
return MP_OBJ_NEW_SMALL_INT(item->time);
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_timeq_peektime_obj, mod_timeq_peektime);
|
||||
|
||||
#if DEBUG
|
||||
STATIC mp_obj_t mod_timeq_dump(mp_obj_t heap_in) {
|
||||
mp_obj_timeq_t *heap = timeq_get_heap(heap_in);
|
||||
for (int i = 0; i < heap->len; i++) {
|
||||
printf(UINT_FMT "\t%p\t%p\n", heap->items[i].time,
|
||||
MP_OBJ_TO_PTR(heap->items[i].callback), MP_OBJ_TO_PTR(heap->items[i].args));
|
||||
}
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_timeq_dump_obj, mod_timeq_dump);
|
||||
#endif
|
||||
|
||||
STATIC mp_obj_t timeq_unary_op(mp_unary_op_t op, mp_obj_t self_in) {
|
||||
mp_obj_timeq_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
switch (op) {
|
||||
case MP_UNARY_OP_BOOL:
|
||||
return mp_obj_new_bool(self->len != 0);
|
||||
case MP_UNARY_OP_LEN:
|
||||
return MP_OBJ_NEW_SMALL_INT(self->len);
|
||||
default:
|
||||
return MP_OBJ_NULL; // op not supported
|
||||
}
|
||||
}
|
||||
|
||||
STATIC const mp_rom_map_elem_t timeq_locals_dict_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR_push), MP_ROM_PTR(&mod_timeq_heappush_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_pop), MP_ROM_PTR(&mod_timeq_heappop_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_peektime), MP_ROM_PTR(&mod_timeq_peektime_obj) },
|
||||
#if DEBUG
|
||||
{ MP_ROM_QSTR(MP_QSTR_dump), MP_ROM_PTR(&mod_timeq_dump_obj) },
|
||||
#endif
|
||||
};
|
||||
|
||||
STATIC MP_DEFINE_CONST_DICT(timeq_locals_dict, timeq_locals_dict_table);
|
||||
|
||||
STATIC MP_DEFINE_CONST_OBJ_TYPE(
|
||||
timeq_type,
|
||||
MP_QSTR_timeq,
|
||||
MP_TYPE_FLAG_NONE,
|
||||
make_new, timeq_make_new,
|
||||
unary_op, timeq_unary_op,
|
||||
locals_dict, &timeq_locals_dict
|
||||
);
|
||||
|
||||
STATIC const mp_rom_map_elem_t mp_module_timeq_globals_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_timeq) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_timeq), MP_ROM_PTR(&timeq_type) },
|
||||
};
|
||||
|
||||
STATIC MP_DEFINE_CONST_DICT(mp_module_timeq_globals, mp_module_timeq_globals_table);
|
||||
|
||||
const mp_obj_module_t mp_module_timeq = {
|
||||
.base = { &mp_type_module },
|
||||
.globals = (mp_obj_dict_t *)&mp_module_timeq_globals,
|
||||
};
|
||||
|
||||
MP_REGISTER_EXTENSIBLE_MODULE(MP_QSTR_timeq, mp_module_timeq);
|
||||
|
||||
#endif // MICROPY_PY_TIMEQ
|
|
@ -83,7 +83,6 @@
|
|||
#define MICROPY_BLUETOOTH_NIMBLE (1)
|
||||
#define MICROPY_BLUETOOTH_NIMBLE_BINDINGS_ONLY (1)
|
||||
#endif
|
||||
#define MICROPY_PY_TIMEQ (1)
|
||||
#define MICROPY_PY_HASHLIB_SHA1 (1)
|
||||
#define MICROPY_PY_HASHLIB_SHA256 (1)
|
||||
#define MICROPY_PY_CRYPTOLIB (1)
|
||||
|
|
|
@ -11,7 +11,6 @@
|
|||
#define MICROPY_PY_GENERATOR_PEND_THROW (0)
|
||||
#define MICROPY_PY_MATH (0)
|
||||
#define MICROPY_PY_HEAPQ (0)
|
||||
#define MICROPY_PY_TIMEQ (0)
|
||||
#define MICROPY_PY_THREAD (0)
|
||||
|
||||
// peripheral config
|
||||
|
|
|
@ -11,7 +11,6 @@
|
|||
#define MICROPY_PY_GENERATOR_PEND_THROW (1)
|
||||
#define MICROPY_PY_MATH (1)
|
||||
#define MICROPY_PY_HEAPQ (1)
|
||||
#define MICROPY_PY_TIMEQ (1)
|
||||
#define MICROPY_PY_THREAD (0) // disable ARM_THUMB_FP using vldr due to RA has single float only
|
||||
|
||||
// peripheral config
|
||||
|
|
|
@ -11,7 +11,6 @@
|
|||
#define MICROPY_PY_GENERATOR_PEND_THROW (1)
|
||||
#define MICROPY_PY_MATH (1)
|
||||
#define MICROPY_PY_HEAPQ (1)
|
||||
#define MICROPY_PY_TIMEQ (1)
|
||||
#define MICROPY_PY_THREAD (0) // disable ARM_THUMB_FP using vldr due to RA has single float only
|
||||
|
||||
// peripheral config
|
||||
|
|
|
@ -11,7 +11,6 @@
|
|||
#define MICROPY_PY_GENERATOR_PEND_THROW (1)
|
||||
#define MICROPY_PY_MATH (1)
|
||||
#define MICROPY_PY_HEAPQ (1)
|
||||
#define MICROPY_PY_TIMEQ (1)
|
||||
#define MICROPY_PY_THREAD (0) // disable ARM_THUMB_FP using vldr due to RA has single float only
|
||||
|
||||
// peripheral config
|
||||
|
|
|
@ -11,7 +11,6 @@
|
|||
#define MICROPY_PY_GENERATOR_PEND_THROW (0)
|
||||
#define MICROPY_PY_MATH (0)
|
||||
#define MICROPY_PY_HEAPQ (0)
|
||||
#define MICROPY_PY_TIMEQ (0)
|
||||
#define MICROPY_PY_THREAD (0)
|
||||
|
||||
// peripheral config
|
||||
|
|
|
@ -102,9 +102,6 @@
|
|||
#define MICROPY_PY_TIME_GMTIME_LOCALTIME_MKTIME (1)
|
||||
#define MICROPY_PY_TIME_TIME_TIME_NS (1)
|
||||
#define MICROPY_PY_TIME_INCLUDEFILE "ports/renesas-ra/modtime.c"
|
||||
#ifndef MICROPY_PY_TIMEQ
|
||||
#define MICROPY_PY_TIMEQ (1)
|
||||
#endif
|
||||
#ifndef MICROPY_PY_MACHINE
|
||||
#define MICROPY_PY_MACHINE (1)
|
||||
#ifndef MICROPY_PY_MACHINE_BITSTREAM
|
||||
|
|
|
@ -18,7 +18,6 @@
|
|||
#define MICROPY_PY_STM (0)
|
||||
#define MICROPY_PY_PYB_LEGACY (0)
|
||||
#define MICROPY_PY_HEAPQ (0)
|
||||
#define MICROPY_PY_TIMEQ (0)
|
||||
|
||||
#define MICROPY_HW_ENABLE_INTERNAL_FLASH_STORAGE (0)
|
||||
#define MICROPY_HW_ENABLE_RTC (1)
|
||||
|
|
|
@ -10,7 +10,6 @@
|
|||
#define MICROPY_PY_STM (0)
|
||||
#define MICROPY_PY_PYB_LEGACY (0)
|
||||
#define MICROPY_PY_HEAPQ (0)
|
||||
#define MICROPY_PY_TIMEQ (0)
|
||||
#define MICROPY_PY_FRAMEBUF (0)
|
||||
|
||||
#define MICROPY_HW_ENABLE_RTC (1)
|
||||
|
|
|
@ -18,7 +18,6 @@
|
|||
#define MICROPY_PY_STM (0)
|
||||
#define MICROPY_PY_PYB_LEGACY (0)
|
||||
#define MICROPY_PY_HEAPQ (0)
|
||||
#define MICROPY_PY_TIMEQ (0)
|
||||
|
||||
#define MICROPY_PY_MACHINE_BITSTREAM (0)
|
||||
|
||||
|
|
|
@ -12,7 +12,6 @@
|
|||
#define MICROPY_PY_STM (0)
|
||||
#define MICROPY_PY_PYB_LEGACY (0)
|
||||
#define MICROPY_PY_HEAPQ (0)
|
||||
#define MICROPY_PY_TIMEQ (0)
|
||||
|
||||
#define MICROPY_HW_ENABLE_RTC (1)
|
||||
#define MICROPY_HW_ENABLE_ADC (1)
|
||||
|
|
|
@ -17,7 +17,6 @@
|
|||
#define MICROPY_PY_STM (0)
|
||||
#define MICROPY_PY_PYB_LEGACY (0)
|
||||
#define MICROPY_PY_HEAPQ (0)
|
||||
#define MICROPY_PY_TIMEQ (0)
|
||||
|
||||
#define MICROPY_HW_HAS_FLASH (1)
|
||||
#define MICROPY_HW_ENABLE_RTC (1)
|
||||
|
|
|
@ -108,9 +108,6 @@
|
|||
#define MICROPY_PY_TIME_GMTIME_LOCALTIME_MKTIME (1)
|
||||
#define MICROPY_PY_TIME_TIME_TIME_NS (1)
|
||||
#define MICROPY_PY_TIME_INCLUDEFILE "ports/stm32/modtime.c"
|
||||
#ifndef MICROPY_PY_TIMEQ
|
||||
#define MICROPY_PY_TIMEQ (1)
|
||||
#endif
|
||||
#define MICROPY_PY_LWIP_SOCK_RAW (MICROPY_PY_LWIP)
|
||||
#ifndef MICROPY_PY_MACHINE
|
||||
#define MICROPY_PY_MACHINE (1)
|
||||
|
|
|
@ -364,7 +364,7 @@ STATIC mp_obj_t extra_coverage(void) {
|
|||
mp_repl_autocomplete("import ", 7, &mp_plat_print, &str); // expect the list of builtins
|
||||
len = mp_repl_autocomplete("import ti", 9, &mp_plat_print, &str); // expect "me"
|
||||
mp_printf(&mp_plat_print, "%.*s\n", (int)len, str);
|
||||
mp_repl_autocomplete("import time", 11, &mp_plat_print, &str); // expect "time timeq"
|
||||
mp_repl_autocomplete("import m", 8, &mp_plat_print, &str); // expect "micropython machine math"
|
||||
|
||||
mp_store_global(MP_QSTR_sys, mp_import_name(MP_QSTR_sys, mp_const_none, MP_OBJ_NEW_SMALL_INT(0)));
|
||||
mp_repl_autocomplete("sys.", 4, &mp_plat_print, &str); // expect dir(sys)
|
||||
|
|
|
@ -100,9 +100,6 @@
|
|||
#define MICROPY_PY_TIME_CUSTOM_SLEEP (1)
|
||||
#define MICROPY_PY_TIME_INCLUDEFILE "ports/unix/modtime.c"
|
||||
|
||||
// Enable the utimeq module used by the previous (v2) version of uasyncio.
|
||||
#define MICROPY_PY_TIMEQ (1)
|
||||
|
||||
#if MICROPY_PY_SSL
|
||||
#define MICROPY_PY_HASHLIB_MD5 (1)
|
||||
#define MICROPY_PY_HASHLIB_SHA1 (1)
|
||||
|
|
|
@ -148,7 +148,6 @@
|
|||
#define MICROPY_PY_JSON (1)
|
||||
#define MICROPY_PY_RE (1)
|
||||
#define MICROPY_PY_HEAPQ (1)
|
||||
#define MICROPY_PY_TIMEQ (1)
|
||||
#define MICROPY_PY_HASHLIB (1)
|
||||
#define MICROPY_PY_BINASCII (1)
|
||||
#define MICROPY_PY_BINASCII_CRC32 (1)
|
||||
|
|
|
@ -18,7 +18,6 @@
|
|||
<PyExtModSource Include="$(PyBaseDir)extmod\modre.c" />
|
||||
<PyExtModSource Include="$(PyBaseDir)extmod\modselect.c" />
|
||||
<PyExtModSource Include="$(PyBaseDir)extmod\modtime.c" />
|
||||
<PyExtModSource Include="$(PyBaseDir)extmod\modtimeq.c" />
|
||||
<PyExtModSource Include="$(PyBaseDir)extmod\modzlib.c" />
|
||||
<PyExtModSource Include="$(PyBaseDir)extmod\virtpin.c" />
|
||||
<PyExtModSource Include="$(PyBaseDir)extmod\vfs.c" />
|
||||
|
|
|
@ -1600,11 +1600,6 @@ typedef double mp_float_t;
|
|||
#define MICROPY_PY_HEAPQ (MICROPY_CONFIG_ROM_LEVEL_AT_LEAST_EXTRA_FEATURES)
|
||||
#endif
|
||||
|
||||
// Optimized heap queue for relative timestamps (only used by uasyncio v2)
|
||||
#ifndef MICROPY_PY_TIMEQ
|
||||
#define MICROPY_PY_TIMEQ (0)
|
||||
#endif
|
||||
|
||||
#ifndef MICROPY_PY_HASHLIB
|
||||
#define MICROPY_PY_HASHLIB (MICROPY_CONFIG_ROM_LEVEL_AT_LEAST_EXTRA_FEATURES)
|
||||
#endif
|
||||
|
|
|
@ -1,146 +0,0 @@
|
|||
# Test for timeq module which implements task queue with support for
|
||||
# wraparound time (time.ticks_ms() style).
|
||||
try:
|
||||
from time import ticks_add, ticks_diff
|
||||
from timeq import timeq
|
||||
except ImportError:
|
||||
print("SKIP")
|
||||
raise SystemExit
|
||||
|
||||
DEBUG = 0
|
||||
|
||||
MAX = ticks_add(0, -1)
|
||||
MODULO_HALF = MAX // 2 + 1
|
||||
|
||||
if DEBUG:
|
||||
|
||||
def dprint(*v):
|
||||
print(*v)
|
||||
|
||||
else:
|
||||
|
||||
def dprint(*v):
|
||||
pass
|
||||
|
||||
|
||||
# Try not to crash on invalid data
|
||||
h = timeq(10)
|
||||
try:
|
||||
h.push(1)
|
||||
assert False
|
||||
except TypeError:
|
||||
pass
|
||||
|
||||
try:
|
||||
h.pop(1)
|
||||
assert False
|
||||
except IndexError:
|
||||
pass
|
||||
|
||||
# unsupported unary op
|
||||
try:
|
||||
~h
|
||||
assert False
|
||||
except TypeError:
|
||||
pass
|
||||
|
||||
# pushing on full queue
|
||||
h = timeq(1)
|
||||
h.push(1, 0, 0)
|
||||
try:
|
||||
h.push(2, 0, 0)
|
||||
assert False
|
||||
except IndexError:
|
||||
pass
|
||||
|
||||
# popping into invalid type
|
||||
try:
|
||||
h.pop([])
|
||||
assert False
|
||||
except TypeError:
|
||||
pass
|
||||
|
||||
# length
|
||||
assert len(h) == 1
|
||||
|
||||
# peektime
|
||||
assert h.peektime() == 1
|
||||
|
||||
# peektime with empty queue
|
||||
try:
|
||||
timeq(1).peektime()
|
||||
assert False
|
||||
except IndexError:
|
||||
pass
|
||||
|
||||
|
||||
def pop_all(h):
|
||||
l = []
|
||||
while h:
|
||||
item = [0, 0, 0]
|
||||
h.pop(item)
|
||||
# print("!", item)
|
||||
l.append(tuple(item))
|
||||
dprint(l)
|
||||
return l
|
||||
|
||||
|
||||
def add(h, v):
|
||||
h.push(v, 0, 0)
|
||||
dprint("-----")
|
||||
# h.dump()
|
||||
dprint("-----")
|
||||
|
||||
|
||||
h = timeq(10)
|
||||
add(h, 0)
|
||||
add(h, MAX)
|
||||
add(h, MAX - 1)
|
||||
add(h, 101)
|
||||
add(h, 100)
|
||||
add(h, MAX - 2)
|
||||
dprint(h)
|
||||
l = pop_all(h)
|
||||
for i in range(len(l) - 1):
|
||||
diff = ticks_diff(l[i + 1][0], l[i][0])
|
||||
assert diff > 0
|
||||
|
||||
|
||||
def edge_case(edge, offset):
|
||||
h = timeq(10)
|
||||
add(h, ticks_add(0, offset))
|
||||
add(h, ticks_add(edge, offset))
|
||||
dprint(h)
|
||||
l = pop_all(h)
|
||||
diff = ticks_diff(l[1][0], l[0][0])
|
||||
dprint(diff, diff > 0)
|
||||
return diff
|
||||
|
||||
|
||||
dprint("===")
|
||||
diff = edge_case(MODULO_HALF - 1, 0)
|
||||
assert diff == MODULO_HALF - 1
|
||||
assert edge_case(MODULO_HALF - 1, 100) == diff
|
||||
assert edge_case(MODULO_HALF - 1, -100) == diff
|
||||
|
||||
# We expect diff to be always positive, per the definition of heappop() which should return
|
||||
# the smallest value.
|
||||
# This is the edge case where this invariant breaks, due to asymmetry of two's-complement
|
||||
# range - there's one more negative integer than positive, so heappushing values like below
|
||||
# will then make ticks_diff() return the minimum negative value. We could make heappop
|
||||
# return them in a different order, but ticks_diff() result would be the same. Conclusion:
|
||||
# never add to a heap values where (a - b) == MODULO_HALF (and which are >= MODULO_HALF
|
||||
# ticks apart in real time of course).
|
||||
dprint("===")
|
||||
diff = edge_case(MODULO_HALF, 0)
|
||||
assert diff == -MODULO_HALF
|
||||
assert edge_case(MODULO_HALF, 100) == diff
|
||||
assert edge_case(MODULO_HALF, -100) == diff
|
||||
|
||||
dprint("===")
|
||||
diff = edge_case(MODULO_HALF + 1, 0)
|
||||
assert diff == MODULO_HALF - 1
|
||||
assert edge_case(MODULO_HALF + 1, 100) == diff
|
||||
assert edge_case(MODULO_HALF + 1, -100) == diff
|
||||
|
||||
print("OK")
|
|
@ -1 +0,0 @@
|
|||
OK
|
|
@ -1,22 +0,0 @@
|
|||
try:
|
||||
from timeq import timeq
|
||||
except ImportError:
|
||||
print("SKIP")
|
||||
raise SystemExit
|
||||
|
||||
h = timeq(10)
|
||||
|
||||
# Check that for 2 same-key items, the queue is stable (pops items
|
||||
# in the same order they were pushed). Unfortunately, this no longer
|
||||
# holds for more same-key values, as the underlying heap structure
|
||||
# is not stable itself.
|
||||
h.push(100, 20, 0)
|
||||
h.push(100, 10, 0)
|
||||
|
||||
res = [0, 0, 0]
|
||||
h.pop(res)
|
||||
assert res == [100, 20, 0]
|
||||
h.pop(res)
|
||||
assert res == [100, 10, 0]
|
||||
|
||||
print("OK")
|
|
@ -1 +0,0 @@
|
|||
OK
|
|
@ -58,11 +58,11 @@ framebuf gc hashlib heapq
|
|||
io json machine math
|
||||
os random re select
|
||||
socket ssl struct sys
|
||||
termios time timeq uctypes
|
||||
websocket zlib
|
||||
termios time uctypes websocket
|
||||
zlib
|
||||
me
|
||||
|
||||
time timeq
|
||||
micropython machine math
|
||||
|
||||
argv atexit byteorder exc_info
|
||||
executable exit getsizeof implementation
|
||||
|
|
|
@ -65,7 +65,6 @@ exclude_tests = (
|
|||
"basics/bytes_compare3.py",
|
||||
"extmod/ticks_diff.py",
|
||||
"extmod/time_ms_us.py",
|
||||
"extmod/heapq_timeq.py",
|
||||
# unicode char issue
|
||||
"extmod/json_loads.py",
|
||||
# doesn't output to python stdout
|
||||
|
|
Loading…
Reference in New Issue