Coroutines aren't great, even C++26 is explicitly avoiding them for its foundational concurrency model.
In any case a good concurrency library doesn't need more than C++14.
RossBencina 2 hours ago [-]
Agree that the code examples look like communicating sequential processes (CSP) and/or async/await-style concurrency (i.e. co-routines in C++). To me this is not "Actors" at all. Actors don't "wait", they receive and send messages, and optionally specify the behavior for handling the next message.
d4ng 2 hours ago [-]
What are actors doing between finishing processing the last message and receiving the next one?
mgaunard 1 hours ago [-]
yield to the event loop
d4ng 1 hours ago [-]
So they're waiting.
mgaunard 41 minutes ago [-]
not really, they yield to other event sources, which is the opposite of waiting (which blocks forward progress and is a violation of real-time guarantees)
DSingularity 24 minutes ago [-]
I think these things can be equivalent. It all depends on the definition of wait.
The simple example can be x86 with monitor/mwait instructions. These will suspend a hardware thread until it can be awoken when the memory write happens to the monitored address. Nothing happens on that cpu thread in the meanwhile. Yet at the same time if things are being virtualized the higher authority exists and it can do something else with the CPU until the write. Same for OS type of event synchronization like Linux futex.
I would argue that the wait abstraction is more powerful. The alternative isn’t powerful enough to enable these kinds of “wake me when I can be useful again” behaviors.
hiyfsch 11 hours ago [-]
Just because coroutines exist doesn’t mean everything should use them for concurrency.
Why would it be better? It’s pretty easy to set up threads in general.
Rohansi 10 hours ago [-]
Threads use more system resources than coroutines so it can be a big deal when you can potentially have thousands of them running.
alfiedotwtf 7 hours ago [-]
The management to handle Threading and IO and not get it wrong is pretty high unless you’re using something like Rust because it guarantees you’re safe, vs letting the routine runtime management handle everything for you for free
whizzter 4 hours ago [-]
Nah, coroutines/async/etc often lives in various threads (ie, the workers can schedule one of them on different threads during the lifetime and they live concurrently), so you still have all the issues of threading (+ new ones since things like thread-local variables aren't reliable if an async/coroutines moves threads between calls).
The main benefit is not having the cost of threads, f.ex. a default thread on Windows has something like 500k of stack iirc, scale that to 10000 concurrent requests and you're looking at 5gb of memory _just for stacks_, compared to a couroutine,etc that has perhaps a few kb's of usage (even if in deep stack-traces).
This is why we have stuff like io_uring these days, the bottleneck moved to the kernel calls (especially with Spectre style attacks) when concurrent costs in the applications went down.
menaerus 4 hours ago [-]
> Nah, coroutines/async/etc often lives in various threads (ie, the workers can schedule one of them on different threads during the lifetime and they live concurrently), so you still have all the issues of threading (+ new ones since things like thread-local variables aren't reliable if an async/coroutines moves threads between calls).
In cooperative scheduling how is it possible to have two coroutines running concurrently?
whizzter 54 minutes ago [-]
You're thinking of older early coroutines or in singlethreaded runtimes (JS).
It's M:N threading, most logical threads/tasks are more lightweight than full OS threads, the logical ones should preferably behave cooperatively but they can be scheduled onto any number of real worker threads (usually these systems picks something like 2x worker threads compared to real CPU/Core count to manage some codepaths not being as well behaved).
Erlang and .NET(with Task/async) uses this model, iirc modern Java does this also (but hides it) and I'd be surprised if the modern async Rust or C++ variations didn't do this as well.
ddorian43 3 hours ago [-]
> aren't reliable if an async/coroutines moves threads between calls
Then just don't move them between threads and you're good with thread locals, no?
whizzter 53 minutes ago [-]
Iirc often the frameworks don't have worker affinity, anyhow environments like .NET has "AsyncLocal" to provide an aware alternative.
rnagulapalle 7 hours ago [-]
[flagged]
khurs 1 hours ago [-]
Why has FoundationDB not been professionalised? Better website, better docs, official GUI?
Is Apple responsible for preventing its wider uptake? Or alternative databases stronger?
fidotron 1 hours ago [-]
Because it converts all normal DBA tasks into development tasks. If this fits your org (and at huge scale it is more likely) then that's fine, but for small/mid/growth places that can be a PITA.
There does seem to be more effort going into an SQL layer, but it's very hard to know what the state of layer dev and direction is these days, especially if you're not located near core devs.
Also how is the supposed Swift rewrite going on?
In any case a good concurrency library doesn't need more than C++14.
The simple example can be x86 with monitor/mwait instructions. These will suspend a hardware thread until it can be awoken when the memory write happens to the monitored address. Nothing happens on that cpu thread in the meanwhile. Yet at the same time if things are being virtualized the higher authority exists and it can do something else with the CPU until the write. Same for OS type of event synchronization like Linux futex.
I would argue that the wait abstraction is more powerful. The alternative isn’t powerful enough to enable these kinds of “wake me when I can be useful again” behaviors.
Why would it be better? It’s pretty easy to set up threads in general.
The main benefit is not having the cost of threads, f.ex. a default thread on Windows has something like 500k of stack iirc, scale that to 10000 concurrent requests and you're looking at 5gb of memory _just for stacks_, compared to a couroutine,etc that has perhaps a few kb's of usage (even if in deep stack-traces).
This is why we have stuff like io_uring these days, the bottleneck moved to the kernel calls (especially with Spectre style attacks) when concurrent costs in the applications went down.
In cooperative scheduling how is it possible to have two coroutines running concurrently?
It's M:N threading, most logical threads/tasks are more lightweight than full OS threads, the logical ones should preferably behave cooperatively but they can be scheduled onto any number of real worker threads (usually these systems picks something like 2x worker threads compared to real CPU/Core count to manage some codepaths not being as well behaved).
Erlang and .NET(with Task/async) uses this model, iirc modern Java does this also (but hides it) and I'd be surprised if the modern async Rust or C++ variations didn't do this as well.
Then just don't move them between threads and you're good with thread locals, no?
Is Apple responsible for preventing its wider uptake? Or alternative databases stronger?
There does seem to be more effort going into an SQL layer, but it's very hard to know what the state of layer dev and direction is these days, especially if you're not located near core devs.
Flow: Actor-based language for C++, used by FoundationDB - https://news.ycombinator.com/item?id=46191763 - Dec 2025 (53 comments)