How do I make an awaitable blocking till a condition is true? (without using while loop)

Viewed 77

How do I make it so that I am stuck awaiting something if the value of it isn't true? for example :

await stuff() # Gets executed
await continueif(x, True) # This only returns when x is True
await morestuff() # Will get to this part when the above statement is executed, which only happens if the condition is true
...

without using while loop

So, ideally

x = True
continueif(x, True)

Should immediately let us pass through but,

x = False
continueif(x, True)

Should never let us pass through until or unless the value of x becomes True sometime during the execution of the program.

1 Answers

I've created something around your code sample to create something minimally run-able. I've used asyncio.Queue, however if your requirement is for a single event asyncio.Event may be a better choice.

It's worth keeping in mind that asyncio is not multi-processing, rather there is one event loop that shares a single thread while some IO (typically) is blocking.

import asyncio
from time import perf_counter

async def make_true(myx: asyncio.Queue):
    await asyncio.sleep(1.0)
    await myx.put(False)
    await asyncio.sleep(1.0)
    await myx.put('hi')
    await asyncio.sleep(1.0)
    await myx.put(True)

async def stuff():
    print(f'{perf_counter()} doing stuff')

async def continueif(myx: asyncio.Queue, condition: bool):
    while True:
        msg = await myx.get()
        if msg == condition:
            print(f'{perf_counter()} {msg} is {condition}')
            break
        else:
            print(f'{perf_counter()} {msg} is not {condition}')

async def morestuff():
    print(f'{perf_counter()} doing more stuff')

async def main():
    x = asyncio.Queue()
    asyncio.create_task(make_true(x))
    await stuff()
    await continueif(x, True)
    await morestuff()

if __name__ == '__main__':
    asyncio.run(main())

Output is:

249083.3551413 doing stuff
249084.3697383 False is not True
249085.3773555 hi is not True
249086.3854538 True is True
249086.385835 doing more stuff

By the way, the while True is only required to parse multiple messages from the asyncio.Queue. If True is the only message the while True: can be omitted.

Related