Reputation: 8995
I am just trying out some MicroPython scripts on LEGO EV3 unit and I am struggling to find any documentation/examples that tells me how to check if a thread is running.
def newMethod():
print("new method")
t1 = threading.Thread(target=newMethod)
while True:
...
if t1.is_alive() is False:
t1.start()
Now this works, apart from the test to see if t1 has been started or not. But it is Python2.7. Thankfully most of it works in microPython apart from the is_alive? I get an error.
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'
Do I need to track this manually? or is there a built in method like python 2.7
Upvotes: 2
Views: 871
Reputation: 35901
is_alive
is not implemented for any of the ports supporting threads currently (in the official repository, don't know about others). So your options are:
For the last case I got curious and came up with this, for the unix port as I don't have Lego to play with, which adds is_alive
to the _thread
module. From thereon it should be fairly easy to get it in your Threading
class. Note this is just to give you an idea of what it takes, and is untested proof of concept, YMMV. Patch:
--- 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*);
Which enables code like:
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))
Which prints True a couple of times, then False.
Upvotes: 1