M
Modular•2mo ago
samufi

How can I write asynchronous code?

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)
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)
^~~~
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)
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 with the nightly built mojo 2024.7.2005 (96a1562c). Addon: I asked this question on the Q&A page and on SO some time ago. Sorry for the double posting; I just do not know what is the best way to get in touch with people who can help. I will keep the copies up to date (or delete them if people think this would be better).
GitHub
mojo/stdlib/src/builtin/coroutine.mojo at 8ec6ba840795b357d0e471f26...
The Mojo Programming Language. Contribute to modularml/mojo development by creating an account on GitHub.
Mojo🔥 changelog | Modular Docs
A history of significant Mojo changes.
6 Replies
Ehsan M. Kermani (Modular)
Async mojo isn't fully baked yet. There've been great amount of progress internally so stay tuned!
samufi
samufi•3w ago
Any updates on this yet @Ehsan M. Kermani ? The issue is still there in the current nightly. Or am I simply doing it wrong? (Anyone here who has used async in mojo??) I was pointed to the answer in a different channel. I need to "delete" the coroutine when waiting for it.
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^)
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^)
Hmmm, it still looks not asynchroneous...
async fn get_time() -> Float64:
var time = now() * 1e-9
sleep(1)
return time

fn call_it():
var a = get_time()
var b = get_time()

print(await a^)
print(await b^)
async fn get_time() -> Float64:
var time = now() * 1e-9
sleep(1)
return time

fn call_it():
var a = get_time()
var b = get_time()

print(await a^)
print(await b^)
If we call call_it, we get
6916.1215625790001 6917.1220518390001
So the functions are not executed in parallel. It seems as if it is waited until await is called. So what am I doing wrong? How could I achive asynchonity?
Jabadahut50
Jabadahut50•3w ago
async isn't parallel computing. It's concurrenty computing. The two are often confused but they are fundamentally different. Async will run when it get's all the things it is waiting on and get's an opening on a singular thread. So awaiting a function means that it will wait to continue until the function it is awaiting has completed and returned, then it will take the return and finish its own work.
ModularBot
ModularBot•3w ago
Congrats @Jabadahut50, you just advanced to level 1!
samufi
samufi•3w ago
Thanks, this is very helpful!
a2svior
a2svior•2w ago
@samufi + 💯 to requesting more documentation on details on how async works in Mojo. I found the documentation there is lacking, I also don't really understand how it works currently By the way, if you're looking for parallel execution there is parallelize
parallelize | Modular Docs
parallelizefunc: fn(Int) capturing -> None
Want results from more Discord servers?
Add your server