Often when something is discovered or invented is far less influential[1] than when it jumps on and hype train.
[1] the discovery is very important for historical and epistemological reasons of course, rewriting the past is bad
Often when something is discovered or invented is far less influential[1] than when it jumps on and hype train.
[1] the discovery is very important for historical and epistemological reasons of course, rewriting the past is bad
Meanwhile Go doesn't have async/await and never will because it doesn't need it; it does greenthreading instead. Java has that too now.
Either way, your code waits on IO like before and does other work while it waits. But instead of the kernel doing the context switching, your runtime does something analogous at a higher layer.
The problem is synchronization becomes extremely hard to reason about. With event loop concurrency, each continuation (callback) becomes effectively a transaction, in which you don't need to worry about anything else modifying your state out from under you. That legitimately makes a lot of things easier.
The Cloudflare Workers runtime actually does both: There's a separate thread for each connection, but within each thread there's an event loop to handle all the concurrent stuff relating to that one connection. This works well because connections rarely need to interact with each other's state, but they need to mess with their own state constantly.
(Actually we have now gone further and stacked a custom green-threading implementation on top of this, but that's really a separate story and only a small incremental optimization.)
If some other transaction commits at just the wrong time, it could change the result of some of these queries but not all. The results would not be consistent with each other.
Btw if you really want consistent multi reads, some DBMSes support setting a read timestamp, but the common ones don't.
Well...if you implemented a relational DBMS server without using threads. To my knowledge, no such DBMS exists, so the distinction seems rather academic.
> Btw if you really want consistent multi reads, some DBMSes support setting a read timestamp, but the common ones don't.
Could you elaborate? I can't say I heard of that mechanism. Perhaps you are referring to something like Oracle flashback queries or SQL Server temporal tables?
Normally, I'd use MVCC-based "snapshot" transaction isolation for consistency between multiple queries, though they would need to be executed serially.
If you want to look at the DBMS itself, well typically there's a separate process per connection, but say it uses threading instead... It'd be thread-safe too. You aren't hitting UB by doing concurrent xacts.
Snapshot xact is what I was thinking about. Not sure about Oracle, but in Spanner they can be parallel.
But one thing I can't figure out: What would be the syntax for promise pipelining, if you aren't using promises to start with?
Oh, great point! That does seem really hard, maybe even intractable. That's definitely a reason to like cooperative concurrency, huh...
Just to tangent even further, but some ideas:
- Do it the ugly way: add an artificial layer of promises in an otherwise pre-emptive, direct-style language. That's just, unfortunately, quite ugly...
- Use a lazy language. Then everything's a promise! Some Haskell optimizations feel kind of like promise pipelining. But I don't really like laziness...
- Use iterator APIs; that's a slightly less artificial way to add layers of promises on top of things, but still weird...
- Punt to the language: build an RPC protocol into the language, and promise pipelining as a guaranteed optimization. Pretty inflexible, and E already tried this...
- Something with choreographic programming and modal-types-for-mobile-code? Such languages explicitly track the "location" of values, and that might be the most natural way to represent ocap promises: a promise is a remote value at some specific location. Unfortunately these languages are all still research projects...
My mental model is that it's a caller who decides how call should be executed (synchroniously or asynchroniously). Synchronious call is when caller waits till completion/error, asynchronious - is when caller puts the call in the background (whatever it means in that language/context) and handle return results later. CSP concurrency model [1] is the closest fit here.
It's not a property of the function to decide how the caller should deal with it. This frustration was partly described in the viral article "What color is your function?" [2], but my main rant about this concurrency approach is that it doesn't match well how we think and reason about concurrent processes, and requires mental cognitive gymnastics to reason about relatively simple code.
Seeing "async/await/Promises/Futures" being a justification of a "protocol" makes little sense to me. I can totally get that they reimagined how to do RPC with first-class async/await primitives, but that doesn't make it a network "protocol".
[1] https://en.wikipedia.org/wiki/Communicating_sequential_proce...
[2] https://journal.stuffwithstuff.com/2015/02/01/what-color-is-...