← All Examples Concurrency
Concurrent Counter
A counter running in its own lightweight process, receiving typed messages. This demonstrates JAPL's Erlang-inspired actor model with type-safe message passing.
Source Code
type Msg =
| Inc
| Get
fn counter(n: Int) {
println("Counter value: " <> show(n))
receive {
Inc => counter(n + 1)
Get => println("Final: " <> show(n))
}
}
fn main() {
println("Starting concurrent counter...")
let pid = spawn(fn() { counter(0) })
send(pid, Inc)
send(pid, Inc)
send(pid, Inc)
send(pid, Get)
println("Messages sent.")
} What This Demonstrates
- Lightweight processes --
spawncreates a new process that runs concurrently. Processes are cheap, not OS threads. - Typed messages -- The
Msgtype defines the message protocol. The compiler ensures only valid messages are sent and received. - Receive blocks --
receiveblocks the process until a matching message arrives, then pattern-matches on it. - Recursive state -- The counter maintains state by recursing with an updated value. No mutable variables needed.
- Fire-and-forget sends --
sendis asynchronous; the main process does not wait for a response.
Line-by-Line Breakdown
type Msg = | Inc | Get- Defines the message protocol for the counter process. Only
IncandGetmessages are valid. fn counter(n: Int)- The process function. It prints the current value, then waits for a message.
receive { Inc => counter(n + 1) ... }- Blocks until a message arrives. On
Inc, it recurses withn + 1, keeping the process alive. OnGet, it prints the final value and terminates (no recursive call). let pid = spawn(fn() { counter(0) })- Spawns a new process running
counter(0). Returns a process identifier (pid) used to send messages. send(pid, Inc)- Sends an
Incmessage to the counter process. This is asynchronous -- execution continues immediately.
Try Modifying
- Add a
Decmessage variant that decrements the counter. - Add a
Resetvariant that sets the counter back to zero. - Spawn multiple counters and send messages to each from
main. - Add a
GetAndReply(Pid)variant that sends the current count back to the caller process.