gleam/erlang/process
Types
An error returned when making a call to a process.
pub type CallError(msg) {
CalleeDown(reason: Dynamic)
CallTimeout
}
Constructors
-
CalleeDown(reason: Dynamic)
The process being called exited before it sent a response.
-
CallTimeout
The process being called did not response within the permitted amount of time.
Values returned when a timer is cancelled.
pub type Cancelled {
TimerNotFound
Cancelled(time_remaining: Int)
}
Constructors
-
TimerNotFound
The timer could not be found. It likely has already triggered.
-
Cancelled(time_remaining: Int)
The timer was found and cancelled before it triggered.
The amount of remaining time before the timer was due to be triggered is returned in milliseconds.
pub type ExitMessage {
ExitMessage(pid: Pid, reason: ExitReason)
}
Constructors
-
ExitMessage(pid: Pid, reason: ExitReason)
pub type ExitReason {
Normal
Killed
Abnormal(reason: String)
}
Constructors
-
Normal
-
Killed
-
Abnormal(reason: String)
A Pid
(or Process identifier) is a reference to an Erlang process. Each
process has a Pid
and it is one of the lowest level building blocks of
inter-process communication in the Erlang and Gleam OTP frameworks.
pub type Pid
A message received when a monitored process exits.
pub type ProcessDown {
ProcessDown(pid: Pid, reason: Dynamic)
}
Constructors
-
ProcessDown(pid: Pid, reason: Dynamic)
pub opaque type ProcessMonitor
A type that enables a process to wait for messages from multiple Subject
s
at the same time, returning whichever message arrives first.
Used with the new_selector
, selecting
, and select
functions.
Examples
let int_subject = new_subject()
let float_subject = new_subject()
send(int_subject, 1)
let selector =
new_selector()
|> selecting(int_subject, int.to_string)
|> selecting(float_subject, float.to_string)
select(selector, 10)
// -> Ok("1")
pub type Selector(payload)
A Subject
is a value that processes can use to send and receive messages
to and from each other in a well typed way.
Each subject is “owned” by the process that created it. Any process can use
the send
function to sent a message of the correct type to the process
that owns the subject, and the owner can use the receive
function or the
Selector
type to receive these messages.
The Subject
type is similar to the “channel” types found in other
languages and the “topic” concept found in some pub-sub systems.
Examples
let subject = new_subject()
// Send a message with the subject
send(subject, "Hello, Joe!")
// Receive the message
receive(subject, within: 10)
pub opaque type Subject(message)
Functions
pub fn call(
subject: Subject(a),
make_request: fn(Subject(b)) -> a,
within timeout: Int,
) -> b
Send a message to a process and wait for a reply.
If the receiving process exits or does not reply within the allowed amount
of time the calling process crashes. If you wish an error to be returned
instead see the try_call
function.
The within
parameter specifies the timeout duration in milliseconds.
pub fn call_forever(
subject: Subject(a),
make_request: fn(Subject(b)) -> a,
) -> b
Similar to the call
function but will wait forever for a message to
arrive rather than timing out after a specified amount of time.
If the receiving process exits, the calling process crashes.
If you wish an error to be returned instead see the try_call_forever
function.
pub fn cancel_timer(timer: Timer) -> Cancelled
Cancel a given timer, causing it not to trigger if it has not done already.
pub fn demonitor_process(monitor monitor: ProcessMonitor) -> Nil
Remove the monitor for a process so that when the monitor process exits a
ProcessDown
message is not sent to the monitoring process.
If the message has already been sent it is removed from the monitoring process’ mailbox.
pub fn deselecting(
selector: Selector(a),
for subject: Subject(b),
) -> Selector(a)
Remove a new Subject
from the Selector
so that its messages will not be
selected from the receiver process inbox.
pub fn deselecting_process_down(
selector: Selector(a),
monitor: ProcessMonitor,
) -> Selector(a)
Remove a ProcessMonitor
from a Selector
prevoiusly added by
selecting_process_down
. If the ProcessMonitor
is not in the
Selector
it will be returned unchanged.
pub fn flush_messages() -> Nil
Discard all messages in the current process’ mailbox.
Warning: This function may cause other processes to crash if they sent a message to the current process and are waiting for a response, so use with caution.
pub fn is_alive(a: Pid) -> Bool
Check to see whether the process for a given Pid
is alive.
See the Erlang documentation for more information.
pub fn kill(pid: Pid) -> Nil
Send an untrappable kill
exit signal to the target process.
See the documentation for the Erlang erlang:exit
function for more
information.
pub fn link(pid pid: Pid) -> Bool
Creates a link between the calling process and another process.
When a process crashes any linked processes will also crash. This is useful to ensure that groups of processes that depend on each other all either succeed or fail together.
Returns True
if the link was created successfully, returns False
if the
process was not alive and as such could not be linked.
pub fn map_selector(a: Selector(a), b: fn(a) -> b) -> Selector(b)
Add a transformation function to a selector. When a message is received using this selector the transformation function is applied to the message.
This function can be used to change the type of messages received and may
be useful when combined with the merge_selector
function.
pub fn merge_selector(
a: Selector(a),
b: Selector(a),
) -> Selector(a)
Merge one selector into another, producing a selector that contains the message handlers of both.
If a subject is handled by both selectors the handler function of the second selector is used.
pub fn monitor_process(pid: Pid) -> ProcessMonitor
Start monitoring a process so that when the monitored process exits a message is sent to the monitoring process.
The message is only sent once, when the target process exits. If the process was not alive when this function is called the message will never be received.
The down message can be received with a Selector
and the
selecting_process_down
function.
The process can be demonitored with the demonitor_process
function.
pub fn named(name: Atom) -> Result(Pid, Nil)
Look up a process by name, returning the pid if it exists.
pub fn new_selector() -> Selector(a)
Create a new Selector
which can be used to receive messages on multiple
Subject
s at once.
pub fn new_subject() -> Subject(a)
Create a new Subject
owned by the current process.
pub fn pid_from_dynamic(
from from: Dynamic,
) -> Result(Pid, List(DecodeError))
Checks to see whether a Dynamic
value is a pid, and return the pid if
it is.
Examples
import gleam/dynamic
from_dynamic(dynamic.from(process.self()))
// -> Ok(process.self())
from_dynamic(dynamic.from(123))
// -> Error([DecodeError(expected: "Pid", found: "Int", path: [])])
pub fn receive(
from subject: Subject(a),
within timeout: Int,
) -> Result(a, Nil)
Receive a message that has been sent to current process using the Subject
.
If there is not an existing message for the Subject
in the process’
mailbox or one does not arrive within
the permitted timeout then the
Error(Nil)
is returned.
Only the process that is owner of the Subject
can receive a message using
it. If a process that does not own the Subject
attempts to receive with it
then it will not receive a message.
To wait for messages from multiple Subject
s at the same time see the
Selector
type.
The within
parameter specifies the timeout duration in milliseconds.
pub fn register(pid: Pid, name: Atom) -> Result(Nil, Nil)
Register a process under a given name, allowing it to be looked up using
the named
function.
This function will return an error under the following conditions:
- The process for the pid no longer exists.
- The name has already been registered.
- The process already has a name.
- The name is the atom
undefined
, which is reserved by Erlang.
pub fn select(
from from: Selector(a),
within within: Int,
) -> Result(a, Nil)
Receive a message that has been sent to current process using any of the
Subject
s that have been added to the Selector
with the selecting
function.
If there is not an existing message for the Selector
in the process’
mailbox or one does not arrive within
the permitted timeout then the
Error(Nil)
is returned.
Only the process that is owner of the Subject
s can receive a message using
them. If a process that does not own the a Subject
attempts to receive
with it then it will not receive a message.
To wait forever for the next message rather than for a limited amount of
time see the select_forever
function.
The within
parameter specifies the timeout duration in milliseconds.
pub fn select_forever(from from: Selector(a)) -> a
Similar to the select
function but will wait forever for a message to
arrive rather than timing out after a specified amount of time.
pub fn selecting(
selector: Selector(a),
for subject: Subject(b),
mapping transform: fn(b) -> a,
) -> Selector(a)
Add a new Subject
to the Selector
so that its messages can be selected
from the receiver process inbox.
The mapping
function provided with the Subject
can be used to convert
the type of messages received using this Subject
. This is useful for when
you wish to add multiple Subject
s to a Selector
when they have differing
message types. If you do not wish to transform the incoming messages in any
way then the identity
function can be given.
See deselecting
to remove a subject from a selector.
pub fn selecting_anything(
selector: Selector(a),
mapping handler: fn(Dynamic) -> a,
) -> Selector(a)
Add a catch-all handler to a selector that will be used when no other handler in a selector is suitable for a given message.
This may be useful for when you want to ensure that any message in the inbox is handled, or when you need to handle messages from other BEAM languages which do not use subjects or record format messages.
pub fn selecting_process_down(
selector: Selector(a),
monitor: ProcessMonitor,
mapping: fn(ProcessDown) -> a,
) -> Selector(a)
Add a ProcessMonitor
to a Selector
so that the ProcessDown
message can
be received using the Selector
and the select
function. The
ProcessMonitor
can be removed later with
deselecting_process_down
.
pub fn selecting_record2(
selector: Selector(a),
tag: b,
mapping transform: fn(Dynamic) -> a,
) -> Selector(a)
Add a handler to a selector for 2 element tuple messages with a given tag element in the first position.
Typically you want to use the selecting
function with a Subject
instead,
but this function may be useful if you need to receive messages sent from
other BEAM languages that do not use the Subject
type.
pub fn selecting_record3(
selector: Selector(a),
tag: b,
mapping transform: fn(Dynamic, Dynamic) -> a,
) -> Selector(a)
Add a handler to a selector for 3 element tuple messages with a given tag element in the first position.
Typically you want to use the selecting
function with a Subject
instead,
but this function may be useful if you need to receive messages sent from
other BEAM languages that do not use the Subject
type.
pub fn selecting_record4(
selector: Selector(a),
tag: b,
mapping transform: fn(Dynamic, Dynamic, Dynamic) -> a,
) -> Selector(a)
Add a handler to a selector for 4 element tuple messages with a given tag element in the first position.
Typically you want to use the selecting
function with a Subject
instead,
but this function may be useful if you need to receive messages sent from
other BEAM languages that do not use the Subject
type.
pub fn selecting_record5(
selector: Selector(a),
tag: b,
mapping transform: fn(Dynamic, Dynamic, Dynamic, Dynamic) -> a,
) -> Selector(a)
Add a handler to a selector for 5 element tuple messages with a given tag element in the first position.
Typically you want to use the selecting
function with a Subject
instead,
but this function may be useful if you need to receive messages sent from
other BEAM languages that do not use the Subject
type.
pub fn selecting_record6(
selector: Selector(a),
tag: b,
mapping transform: fn(
Dynamic,
Dynamic,
Dynamic,
Dynamic,
Dynamic,
) -> a,
) -> Selector(a)
Add a handler to a selector for 6 element tuple messages with a given tag element in the first position.
Typically you want to use the selecting
function with a Subject
instead,
but this function may be useful if you need to receive messages sent from
other BEAM languages that do not use the Subject
type.
pub fn selecting_record7(
selector: Selector(a),
tag: b,
mapping transform: fn(
Dynamic,
Dynamic,
Dynamic,
Dynamic,
Dynamic,
Dynamic,
) -> a,
) -> Selector(a)
Add a handler to a selector for 7 element tuple messages with a given tag element in the first position.
Typically you want to use the selecting
function with a Subject
instead,
but this function may be useful if you need to receive messages sent from
other BEAM languages that do not use the Subject
type.
pub fn selecting_record8(
selector: Selector(a),
tag: b,
mapping transform: fn(
Dynamic,
Dynamic,
Dynamic,
Dynamic,
Dynamic,
Dynamic,
Dynamic,
) -> a,
) -> Selector(a)
Add a handler to a selector for 8 element tuple messages with a given tag element in the first position.
Typically you want to use the selecting
function with a Subject
instead,
but this function may be useful if you need to receive messages sent from
other BEAM languages that do not use the Subject
type.
pub fn selecting_trapped_exits(
selector: Selector(a),
handler: fn(ExitMessage) -> a,
) -> Selector(a)
Add a handler for trapped exit messages. In order for these messages to be
sent to the process when a linked process exits the process must call the
trap_exit
beforehand.
pub fn send(subject: Subject(a), message: a) -> Nil
Send a message to a process using a Subject
. The message must be of the
type that the Subject
accepts.
This function does not wait for the Subject
owner process to call the
receive
function, instead it returns once the message has been placed in
the process’ mailbox.
Ordering
If process P1 sends two messages to process P2 it is guaranteed that process P1 will receive the messages in the order they were sent.
If you wish to receive the messages in a different order you can send them
on two different subjects and the receiver function can call the receive
function for each subject in the desired order, or you can write some Erlang
code to perform a selective receive.
Examples
let subject = new_subject()
send(subject, "Hello, Joe!")
pub fn send_abnormal_exit(pid: Pid, reason: String) -> Nil
Sends an exit signal to a process, indicating that the process is to shut down due to an abnormal reason such as a failure.
See the Erlang documentation for more information.
pub fn send_after(
subject: Subject(a),
delay: Int,
message: a,
) -> Timer
Send a message over a channel after a specified number of milliseconds.
pub fn send_exit(to pid: Pid) -> Nil
Sends an exit signal to a process, indicating that the process is to shut down.
See the Erlang documentation for more information.
pub fn sleep(a: Int) -> Nil
Suspends the process calling this function for the specified number of milliseconds.
pub fn sleep_forever() -> Nil
Suspends the process forever! This may be useful for suspending the main process in a Gleam program when it has no more work to do but we want other processes to continue to work.
pub fn start(
running implementation: fn() -> a,
linked link: Bool,
) -> Pid
Create a new Erlang process that runs concurrently to the creator. In other languages this might be called a fibre, a green thread, or a coroutine.
If linked
is True
then the created process is linked to the creator
process. When a process terminates an exit signal is sent to all other
processes that are linked to it, causing the process to either terminate or
have to handle the signal.
More can be read about processes and links in the Erlang documentation.
pub fn subject_owner(subject: Subject(a)) -> Pid
Get the owner process for a Subject
. This is the process that created the
Subject
and will receive messages sent with it.
pub fn trap_exits(a: Bool) -> Nil
Set whether the current process is to trap exit signals or not.
When not trapping exits if a linked process crashes the exit signal propagates to the process which will also crash. This is the normal behaviour before this function is called.
When trapping exits (after this function is called) if a linked process
crashes an exit message is sent to the process instead. These messages can
be handled with the selecting_trapped_exits
function.
pub fn try_call(
subject: Subject(a),
make_request: fn(Subject(b)) -> a,
within timeout: Int,
) -> Result(b, CallError(b))
Send a message to a process and wait for a reply.
If the receiving process exits or does not reply within the allowed amount of time then an error is returned.
The within
parameter specifies the timeout duration in milliseconds.
pub fn try_call_forever(
subject: Subject(a),
make_request: fn(Subject(b)) -> a,
) -> Result(b, CallError(c))
Similar to the try_call
function but will wait forever for a message
to arrive rather than timing out after a specified amount of time.
If the receiving process exits then an error is returned.
pub fn unlink(pid: Pid) -> Nil
Removes any existing link between the caller process and the target process.
pub fn unregister(name: Atom) -> Result(Nil, Nil)
Un-register a process name, after which the process can no longer be looked up by that name, and both the name and the process can be re-used in other registrations.
It is possible to un-register process that are not from your application, including those from Erlang/OTP itself. This is not recommended and will likely result in undesirable behaviour and crashes.