Проверка, запущен ли поток в MicroPython - PullRequest
2 голосов
/ 28 мая 2019

Я просто пробую некоторые скрипты MicroPython на модуле LEGO EV3, и я пытаюсь найти любую документацию / примеры, которые говорят мне, как проверить, работает ли поток.

def newMethod():
    print("new method")
t1 = threading.Thread(target=newMethod)
while True:
    ...
    if t1.is_alive() is False:
        t1.start()

Теперь это работает,кроме теста, чтобы увидеть, был ли t1 запущен или нет.Но это Python2.7.К счастью, большинство из них работает в microPython, кроме is_alive?Я получаю сообщение об ошибке.

Traceback (most recent call last):
  File "./micro.py", line 79, in <module>
  File "./micro.py", line 73, in <module>
AttributeError: 'Thread' object has no attribute 'is_alive'

Нужно ли отслеживать это вручную?или есть встроенный метод, как Python 2.7

1 Ответ

1 голос
/ 29 мая 2019

is_alive в настоящее время не реализован ни для одного из портов, поддерживающих потоки (в официальном хранилище не знаю о других).Итак, ваши варианты:

  • отслеживать это вручную
  • использовать другую логику в вашем коде, чтобы вам это не понадобилось
  • создать запрос функции
  • реализовать его самостоятельно для используемого вами порта (если вы знаете C, это может быть относительно просто, так как реализация потоков обычно имеет встроенный способ сообщить о своем состоянии)

В последнем случае мне стало любопытно, и я придумал это для порта Unix, поскольку у меня нет Lego, с которым можно поиграть, что добавляет is_alive к модулю _thread.Оттуда должно быть довольно легко получить его в вашем Threading классе.Обратите внимание, что это просто, чтобы дать вам представление о том, что нужно, и является непроверенным доказательством концепции, YMMV.Патч:

--- a/ports/unix/mpthreadport.c
+++ b/ports/unix/mpthreadport.c
@@ -174,7 +174,20 @@ void mp_thread_start(void) {
     pthread_mutex_unlock(&thread_mutex);
 }

-void mp_thread_create(void *(*entry)(void*), void *arg, size_t *stack_size) {
+int mp_thread_is_alive(void* id) {
+    int ready = 0;
+    pthread_mutex_lock(&thread_mutex);
+    for (thread_t *th = thread; th != NULL; th = th->next) {
+        if (th->id == (pthread_t)id && th->ready) {
+            ready = 1;
+            break;
+        }
+    }
+    pthread_mutex_unlock(&thread_mutex);
+    return ready;
+}
+
+void* mp_thread_create(void *(*entry)(void*), void *arg, size_t *stack_size) {
     // default stack size is 8k machine-words
     if (*stack_size == 0) {
         *stack_size = 8192 * BYTES_PER_WORD;
@@ -225,7 +238,7 @@ void mp_thread_create(void *(*entry)(void*), void *arg, size_t *stack_size) {

     pthread_mutex_unlock(&thread_mutex);

-    return;
+    return (void*) th->id;

 er:
     mp_raise_OSError(ret);
diff --git a/py/modthread.c b/py/modthread.c
index 91237a7..246dd5c 100644
--- a/py/modthread.c
+++ b/py/modthread.c
@@ -264,9 +264,7 @@ STATIC mp_obj_t mod_thread_start_new_thread(size_t n_args, const mp_obj_t *args)
     th_args->fun = args[0];

     // spawn the thread!
-    mp_thread_create(thread_entry, th_args, &th_args->stack_size);
-
-    return mp_const_none;
+    return mp_obj_new_int_from_uint((uintptr_t)mp_thread_create(thread_entry, th_args, &th_args->stack_size));
 }
 STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_thread_start_new_thread_obj, 2, 3, mod_thread_start_new_thread);

@@ -275,6 +273,11 @@ STATIC mp_obj_t mod_thread_exit(void) {
 }
 STATIC MP_DEFINE_CONST_FUN_OBJ_0(mod_thread_exit_obj, mod_thread_exit);

+STATIC mp_obj_t mod_thread_is_alive(mp_obj_t id) {
+    return mp_obj_new_bool(mp_thread_is_alive((void*) mp_obj_get_int(id)));
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_thread_is_alive_obj, mod_thread_is_alive);
+
 STATIC mp_obj_t mod_thread_allocate_lock(void) {
     return MP_OBJ_FROM_PTR(mp_obj_new_thread_lock());
 }
@@ -287,6 +290,7 @@ STATIC const mp_rom_map_elem_t mp_module_thread_globals_table[] = {
     { MP_ROM_QSTR(MP_QSTR_stack_size), MP_ROM_PTR(&mod_thread_stack_size_obj) },
     { MP_ROM_QSTR(MP_QSTR_start_new_thread), MP_ROM_PTR(&mod_thread_start_new_thread_obj) },
     { MP_ROM_QSTR(MP_QSTR_exit), MP_ROM_PTR(&mod_thread_exit_obj) },
+    { MP_ROM_QSTR(MP_QSTR_is_alive), MP_ROM_PTR(&mod_thread_is_alive_obj) },
     { MP_ROM_QSTR(MP_QSTR_allocate_lock), MP_ROM_PTR(&mod_thread_allocate_lock_obj) },
 };

diff --git a/py/mpthread.h b/py/mpthread.h
index 602df83..46f1a3a 100644
--- a/py/mpthread.h
+++ b/py/mpthread.h
@@ -40,7 +40,8 @@ struct _mp_state_thread_t;

 struct _mp_state_thread_t *mp_thread_get_state(void);
 void mp_thread_set_state(void *state);
-void mp_thread_create(void *(*entry)(void*), void *arg, size_t *stack_size);
+void* mp_thread_create(void *(*entry)(void*), void *arg, size_t *stack_size);
+int mp_thread_is_alive(void*);

Который включает код вроде:

import _thread
import utime

def Entry():
    utime.sleep_ms(1)

t = _thread.start_new_thread(Entry, ())
for i in range(10):
    print('thread alive', _thread.is_alive(t))

Который пару раз печатает True, затем False.

...