1

How can I implement asynchroneous code in mojo (using async etc.)?

In the Changelog, I find the following example (slightly adjusted):

async fn add_three(a: Int, b: Int, c: Int) -> Int:
    return a + b + c

async fn call_it():
    var task = add_three(1, 2, 3)
    print(await task)

This gives me the following compiler error:

test_async.mojo:39:17: error: 'Coroutine[Int, {}]' is not copyable because it has no '__copyinit__'
    print(await task)
                ^~~~

I do not understand this error, as I thought that Coroutine is register passable (as visible in the source code). What works is

async fn add_three(a: Int, b: Int, c: Int) -> Int:
    return a + b + c

async fn call_it():
    var task = await add_three(1, 2, 3)
    print(task)

However, if I always put await on the right hand side, I will never be able to execute code asynchroneously, as I am always waiting until the line has finished. What am I doing wrong / where is my misconception? (Or is this simply a bug?)

In the changelog it furthermore says that tasks can be "resumed" after completion (see here). What is meant by "resume" and how do I do that?

I am working on the current nightly built: mojo 2024.7.2005 (96a1562c).

Note: I have also posted this question on mojo's Q&A page but have not seen any reaction so far. I will update this post if I recieve an answer there.

1 Answer 1

1

The problem is that a coroutine (the result of an async function) is not copyable; i.e., it can only exist once. This makes sense, as a copy would need to point to the same asynchroneous task, which would mean that the copies are not "really" indepent on one another.

The solution is to invoke the move init, which can be done via the ^ operator here. This operator ensures that the value of the variable with the coroutine is not used afterwards anymore and transfers the ownership.

async fn call_it():
    var task = add_three(1, 2, 3)
    print(await task^)

This works like charm. Similarly, we could also move the finished result to another, "classical" variable (i.e., not a coroutine):

async fn call_it():
    var task = add_three(1, 2, 3)
    var other = await task^
    print(other)
Sign up to request clarification or add additional context in comments.

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.