extmod/uos_dupterm: Use native C stream methods on dupterm object.

This patch changes dupterm to call the native C stream methods on the
connected stream objects, instead of calling the Python readinto/write
methods.  This is much more efficient for native stream objects like UART
and webrepl and doesn't require allocating a special dupterm array.

This change is a minor breaking change from the user's perspective because
dupterm no longer accepts pure user stream objects to duplicate on.  But
with the recent addition of uio.IOBase it is possible to still create such
classes just by inheriting from uio.IOBase, for example:

    import uio, uos

    class MyStream(uio.IOBase):
        def write(self, buf):
            # existing write implementation
        def readinto(self, buf):
            # existing readinto implementation

    uos.dupterm(MyStream())
This commit is contained in:
Damien George 2018-06-12 15:06:11 +10:00
parent 5042d98514
commit 035906419d
3 changed files with 16 additions and 28 deletions

View File

@ -60,25 +60,29 @@ int mp_uos_dupterm_rx_chr(void) {
nlr_buf_t nlr; nlr_buf_t nlr;
if (nlr_push(&nlr) == 0) { if (nlr_push(&nlr) == 0) {
mp_obj_t readinto_m[3]; byte buf[1];
mp_load_method(MP_STATE_VM(dupterm_objs[idx]), MP_QSTR_readinto, readinto_m); int errcode;
readinto_m[2] = MP_STATE_VM(dupterm_arr_obj); const mp_stream_p_t *stream_p = mp_get_stream_raise(MP_STATE_VM(dupterm_objs[idx]), MP_STREAM_OP_READ);
mp_obj_t res = mp_call_method_n_kw(1, 0, readinto_m); mp_uint_t out_sz = stream_p->read(MP_STATE_VM(dupterm_objs[idx]), buf, 1, &errcode);
if (res == mp_const_none) { if (out_sz == 0) {
nlr_pop();
} else if (res == MP_OBJ_NEW_SMALL_INT(0)) {
nlr_pop(); nlr_pop();
mp_uos_deactivate(idx, "dupterm: EOF received, deactivating\n", MP_OBJ_NULL); mp_uos_deactivate(idx, "dupterm: EOF received, deactivating\n", MP_OBJ_NULL);
} else { } else if (out_sz == MP_STREAM_ERROR) {
mp_buffer_info_t bufinfo; // errcode is valid
mp_get_buffer_raise(MP_STATE_VM(dupterm_arr_obj), &bufinfo, MP_BUFFER_READ); if (mp_is_nonblocking_error(errcode)) {
nlr_pop(); nlr_pop();
if (*(byte*)bufinfo.buf == mp_interrupt_char) { } else {
mp_raise_OSError(errcode);
}
} else {
// read 1 byte
nlr_pop();
if (buf[0] == mp_interrupt_char) {
// Signal keyboard interrupt to be raised as soon as the VM resumes // Signal keyboard interrupt to be raised as soon as the VM resumes
mp_keyboard_interrupt(); mp_keyboard_interrupt();
return -2; return -2;
} }
return *(byte*)bufinfo.buf; return buf[0];
} }
} else { } else {
mp_uos_deactivate(idx, "dupterm: Exception in read() method, deactivating: ", nlr.ret_val); mp_uos_deactivate(idx, "dupterm: Exception in read() method, deactivating: ", nlr.ret_val);
@ -96,18 +100,7 @@ void mp_uos_dupterm_tx_strn(const char *str, size_t len) {
} }
nlr_buf_t nlr; nlr_buf_t nlr;
if (nlr_push(&nlr) == 0) { if (nlr_push(&nlr) == 0) {
mp_obj_t write_m[3]; mp_stream_write(MP_STATE_VM(dupterm_objs[idx]), str, len, MP_STREAM_RW_WRITE);
mp_load_method(MP_STATE_VM(dupterm_objs[idx]), MP_QSTR_write, write_m);
mp_obj_array_t *arr = MP_OBJ_TO_PTR(MP_STATE_VM(dupterm_arr_obj));
void *org_items = arr->items;
arr->items = (void*)str;
arr->len = len;
write_m[2] = MP_STATE_VM(dupterm_arr_obj);
mp_call_method_n_kw(1, 0, write_m);
arr = MP_OBJ_TO_PTR(MP_STATE_VM(dupterm_arr_obj));
arr->items = org_items;
arr->len = 1;
nlr_pop(); nlr_pop();
} else { } else {
mp_uos_deactivate(idx, "dupterm: Exception in write() method, deactivating: ", nlr.ret_val); mp_uos_deactivate(idx, "dupterm: Exception in write() method, deactivating: ", nlr.ret_val);
@ -133,9 +126,6 @@ STATIC mp_obj_t mp_uos_dupterm(size_t n_args, const mp_obj_t *args) {
MP_STATE_VM(dupterm_objs[idx]) = MP_OBJ_NULL; MP_STATE_VM(dupterm_objs[idx]) = MP_OBJ_NULL;
} else { } else {
MP_STATE_VM(dupterm_objs[idx]) = args[0]; MP_STATE_VM(dupterm_objs[idx]) = args[0];
if (MP_STATE_VM(dupterm_arr_obj) == MP_OBJ_NULL) {
MP_STATE_VM(dupterm_arr_obj) = mp_obj_new_bytearray(1, "");
}
} }
return previous_obj; return previous_obj;

View File

@ -171,7 +171,6 @@ typedef struct _mp_state_vm_t {
#if MICROPY_PY_OS_DUPTERM #if MICROPY_PY_OS_DUPTERM
mp_obj_t dupterm_objs[MICROPY_PY_OS_DUPTERM]; mp_obj_t dupterm_objs[MICROPY_PY_OS_DUPTERM];
mp_obj_t dupterm_arr_obj;
#endif #endif
#if MICROPY_PY_LWIP_SLIP #if MICROPY_PY_LWIP_SLIP

View File

@ -108,7 +108,6 @@ void mp_init(void) {
for (size_t i = 0; i < MICROPY_PY_OS_DUPTERM; ++i) { for (size_t i = 0; i < MICROPY_PY_OS_DUPTERM; ++i) {
MP_STATE_VM(dupterm_objs[i]) = MP_OBJ_NULL; MP_STATE_VM(dupterm_objs[i]) = MP_OBJ_NULL;
} }
MP_STATE_VM(dupterm_arr_obj) = MP_OBJ_NULL;
#endif #endif
#if MICROPY_FSUSERMOUNT #if MICROPY_FSUSERMOUNT