Erlang developed the way it did before people started calling it an Actor model.
The key characteristic is not a state machine, but that:
- first class processes send messages to each other
- messages are queued
- each process is single execution flow. If you want to reenter code, start another process and send messages to it
- process execution can be preempted
- values passed in messages are for the most part, immutable.
- first class support for “links”, where one process gets notified when another process crashes (basis for supervision trees)
The consequences of this design are:
- for the most part, you don’t need mutexs
- spin locks are cheap
- every process can be suspended indefinitely when nothing is in the message queue. This is better than an async reactor.
- processes don’t get “lost” (I am looking at you, Nodejs)
- processes can receive control messages to suspend or shutdown, restart, etc. Most other platforms have to externalize that to say, K8S and such controls are crude.
- errors don’t get “lost” (Nodejs again …)
- repl in production, can inspect the whole system live, under load
- overloaded systems degrades gracefully instead of locking up