4

I have 2 coroutines (co_A, co_B) in different classes (class_A, class_B) that are called regularly by a scheduler. At some time during the execution co_B needs a result that co_A is calculating during its run.

What I would like to do is something like this:

class class_A:
    async def co_A(self):

        # execute time consuming code

        # set result that co_B needs
        self.set_result(result)

        # execute more time consuming code

class class_B:
    async def co_B(self):

        # execute time consuming code

        # wait for result from co_A
        result = await class_A_instance.get_result()

        # execute more time consuming code

My approach is to have an empty Future in class_A that gets filled during co_A and in co_B wait in a loop until the Future is set:

class class_A:
    async def prepare(self):
        self.fut = asyncio.Future()

    async def co_A(self):

        # execute time consuming code

        # set result that co_B needs
        self.fut.set_result(result)

        # execute more time consuming code

class class_B:   
    async def co_B(self):

        # execute time consuming code

        # wait for result from co_A
        while not class_A_instance.fut.done():
            await asyncio.sleep(0)

        result = class_A_instance.fut.result()

        # execute more time consuming code

Is there a better way to do this without having to sleep in a loop until co_A has calculated the result?

2 Answers 2

1

Whole idea of futures is that you can await for it just like for coroutines, tasks, etc.

class class_B:   
    async def co_B(self):

        # execute time consuming code

        # wait for result from co_A
        result = await class_A_instance.fut

        # execute more time consuming code

See section "Things a coroutine can do" here.

Sign up to request clarification or add additional context in comments.

2 Comments

This approach is correct, but it assumes that co_A is already scheduled.
@kwarunek The same assumption is present in the OP's code (the version with the while loop). The nice thing about this solution is that it's more lightweight than an asyncio.Event, and also that it allows transmitting a payload object (whereas an Event only carries a Boolean flag).
1

I would use Event class to synchronize coroutines. @Mikhail approach is 100% correct but doesn't address that you would like to get notified in the middle of co_A.

class A:
    def __init__(self):
        self.partially_ready = asyncio.Event()

    async def prepare(self):
        self.partially_ready.clear()

    async def co_A(self):   
        # execute time consuming code

        # set result that co_B needs
        self.partially_ready.set()
        # execute more time consuming code


class class_B:   
    async def co_B(self):

        # execute time consuming code

        # wait for result from co_A
        await A_instance.partially_ready.wait()
        # here A_instance finished some part you would like to wait

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.