Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to know if threading.Condition.wait(timeout) has timed out or has been notified?

I'm developing an application with some threads, each one running an infinite loop with a time sleep. What I want is to finish all threads once the main one has finished, here an example:

def main():

    display_res_stop = threading.Condition()
    display_result_t = threading.Thread(target=sample_t, args=(display_res_stop, ))
    display_result_t.start()

    time.sleep(4)

    display_res_stop.acquire()
    display_res_stop.notify()
    display_res_stop.release()


def sample_t(stop_cond):
    stop_cond.acquire()

    while True:
        print 5
        c = stop_cond.wait(10)

    stop_cond.release()

if __name__ == '__main__':
    main()

The problem with this solution is that I don't know if condition.wait has finished because the timeout or because has been notified. In the second case while loop should finish.

At first I was doing a time.sleep(t) and using threading events but then the application has to wait until t on all threads has passed.

I'm thinking about a mixed solution using threading.Condition and Event but I don't know if it's the nicest thing to do (Condition for the 'sleep' and Event to replace while True).

like image 604
Jairo Vadillo Avatar asked Apr 29 '15 07:04

Jairo Vadillo


People also ask

How do you check the status of a thread in Python?

is_alive() method is an inbuilt method of the Thread class of the threading module in Python. It uses a Thread object, and checks whether that thread is alive or not, ie, it is still running or not. This method returns True before the run() starts until just after the run() method is executed.

What is the method to retrieve the list of all active threads?

threading. enumerate() returns a list of all Thread objects currently alive.

Which method is used to identify a thread in Python?

Thread object which is created using constructor or run method can be started by using start() method. Whenever a Thread object starts a new thread then internally it's run() method is invoked.

Which lock types can a condition object be associated with?

5. Condition Objects. A condition variable is always associated with some kind of lock; this can be passed in or one will be created by default. Passing one in is useful when several condition variables must share the same lock.


2 Answers

After all it was very simple, I was just focusing on the wrong thing: I just needed a sleep that could be stopped with an event and thats what Event.wait(t) does. The problem then, can be solved just with Events.

import threading
import time

def sample_thread(stop_ev):
    while not stop_ev.is_set():
        print 'Thread iteration'
        stop_ev.wait(0.1)

def main():
    stop_ev = threading.Event()
    sample_t = threading.Thread(target=sample_thread, args=(stop_ev, ))
    sample_t.start()

    # Other stuff here, sleep is just dummy
    time.sleep(14)

    stop_ev.set()

    print 'End reached.'

if __name__ == '__main__':
    main()
like image 183
Jairo Vadillo Avatar answered Nov 15 '22 00:11

Jairo Vadillo


The easy way to do this is to use Python 3.2 or later, or get the backport of the current threading to 3.1/2.7/etc. from PyPI, or just copy the code for that method from, say, 3.4's source.

As the docs for Condition.wait explain:

The return value is True unless a given timeout expired, in which case it is False.

Changed in version 3.2: Previously, the method always returned None.


As a side note, I'm not sure you need a Condition here at all; you're not checking a flag inside the loop, or doing anything else that should be susceptible to a race condition, you're just waiting to be notified. That implies that, as long as you don't need magic auto-reset, an Event should be just fine. And Event.wait has had the True/False return since 2.7/3.1+, rather than 3.2+.

like image 23
abarnert Avatar answered Nov 14 '22 22:11

abarnert