process/process
Working with typed processes in Gleam.
This module allows you to:
- spawn processes
- send and receive messages
- call processes, send a message and expect a reply.
- monitor processes
- link to processes
- supervise processes with the
set_supervisor
andrest_for_one
This module is being developed concurrently with the Midas web framework. It will be extracted before Midas reaches 1.0. Help with this module is greatly appreciated.
You will need these imports for the examples to work
import process/process
import process/process.{Normal, Infinity, From}
Starting and stopping processes
A process is started using process.spawn_link/1
.
The single argument is a function that accepts a receive call and returns an ExitReason
.
This is an example of the simplest process that immediately exits with reason Normal
let pid = process.spawn_link(fn(_receive) {
Normal
})
Sending and receiving messages
Here is a simple process that sums all the numbers sent to it.
fn loop(receive, state) {
let value = receive(Infinity)
loop(receive, state + value)
}
let pid = process.spawn_link(loop(_, 0))
process.send(pid, 1)
process.send(pid, 2)
By recursively calling loop this function runs forever. The type of the receive function is parameters by the type of messages it accepts.
Because gleam infers the type of value to be an Int it is known that only integers can be sent to this pid. The following call will not be allowed by the type checker.
process.send(pid, "0")
Normally a process will accept more message types than an Int, This is handled by defining a single type with a constructor for each expected message type.
Calling a process
Send a message to a process an await a reply.
type Messages {
Reverse(From(String), String)
}
fn loop(receive) {
let Reverse(from, str) = receive(Infinity)
process.reply(from, string.reverse(str))
loop(receive)
}
let pid = process.spawn_link(loop(_))
let Ok(reversed) = process.call(pid, Reverse(_, "hello"))
The Reverse
message type includes a from reference that says callers accept a String
type as a response.
Receiving this message works the same way as before, but now we have a from value that we can send a reply to.
Sending a call message uses process.call/2
.
The first argument is a Pid.
The second argument is a function that takes a from reference and creates a message.
Having a constructor for the sent message allows the process library to create a from value. Doing this allows the calling process to receive replies without having to specify them as part of their message contract. Again Gleam ensures we can't send a message that isn't understood and we can't reply with a type that isn't expected.
Types
BarePid
A Pid that is not parameterised by the messages it can receive. Bare Pids are useful when you receive a Pid from a DOWN or EXIT message. They can also be used to check equality between two pids.
pub external type BarePid
CallError
pub type CallError { Timeout Gone }
Constructors
-
Timeout
-
Gone
DemonitorOptions
pub type DemonitorOptions { Flush }
Constructors
-
Flush
ExitReason
Reason for a process to terminate.
In most cases Normal
is the correct value to return from a process's run function.
pub type ExitReason { Normal Kill Killed }
Constructors
-
Normal
-
Kill
-
Killed
From
pub type From(r) { From(Ref, Pid(tuple(Ref, r))) }
Constructors
-
From(Ref, Pid(tuple(Ref, r)))
MonitorType
pub type MonitorType { Process }
Constructors
-
Process
OK
pub type OK { OK(OK) }
Constructors
-
OK(OK)
Pid
Identifier for a process This type is parameterised by the message type acceptable to that process.
pub external type Pid(m)
ProcessFlag
pub type ProcessFlag { TrapExit(Bool) }
Constructors
-
TrapExit(Bool)
Ref
pub external type Ref
Wait
A value in milliseconds or infinity.
pub type Wait { Infinity Milliseconds(Int) }
Constructors
-
Infinity
-
Milliseconds(Int)
Functions
call
pub fn call( pid: Pid(a), constructor: fn(From(b)) -> a, wait: Wait, ) -> Result(a, CallError)
demonitor
pub external fn demonitor(Ref, List(DemonitorOptions)) -> Bool
do_sleep
pub external fn do_sleep(Int) -> OK
exit
pub external fn exit(Pid(m), ExitReason) -> Bool
monitor
pub external fn monitor(MonitorType, Pid(m)) -> Ref
monitor_process
pub fn monitor_process(pid: Pid(a)) -> Ref
process_flag
pub external fn process_flag(ProcessFlag) -> ProcessFlag
receive_reply
pub external fn receive_reply(Ref, Wait) -> Result(r, CallError)
reply
pub fn reply(from: From(a), message: a) -> tuple(Ref, a)
self
pub fn self(_: fn(Wait) -> Result(a, Nil)) -> Pid(a)
send
pub external fn send(Pid(m), m) -> m
spawn_link
pub external fn spawn_link(Run(m)) -> Pid(m)
unsafe_self
pub external fn unsafe_self() -> Pid(m)