Spec-Zone.ru › Elixir 1.8

Процесс

Удобства работы с процессами и словарем процессов.

Помимо функций, доступных в этом модуле, модуль Kernel экспонирует и автоматически импортирует некоторые базовые функциональности, связанные с процессами, доступные через следующие функции:

  • Kernel.spawn/1 и Kernel.spawn/3
  • Kernel.spawn_link/1 и Kernel.spawn_link/3
  • Kernel.spawn_monitor/1 и Kernel.spawn_monitor/3
  • Kernel.self/0
  • Kernel.send/2

Хотя этот модуль предоставляет удобные инструменты низкого уровня для работы с процессами, разработчики обычно используют абстракции, такие как Agent, GenServer, Registry, Supervisor и Task для построения своих систем и прибегают к этому модулю для получения информации, перехвата завершений, связей и мониторинга.

Краткое описание

Типы

dest()

Назначение процесса.

spawn_opt()
spawn_opts()

Функции

alive?(pid)

Указывает, жив ли данный процесс на локальном узле.

cancel_timer(timer_ref, options \\ [])

Отменяет таймер, возвращённый функцией send_after/3.

delete(key)

Удаляет заданный key из словаря процессов.

demonitor(monitor_ref, options \\ [])

Отключает монитор, идентифицированный данным reference.

exit(pid, reason)

Отправляет сигнал выхода с заданным reason процессу pid.

flag(flag, value)

Устанавливает заданный flag в value для вызывающего процесса.

flag(pid, flag, value)

Устанавливает заданный flag в value для данного процесса pid.

get()

Возвращает все пары ключ-значение в словаре процессов.

get(key, default \\ nil)

Возвращает значение для заданного key в словаре процессов или default, если key не задано.

get_keys()

Возвращает все ключи в словаре процессов.

get_keys(value)

Возвращает все ключи в словаре процессов, имеющие заданное value.

group_leader()

Возвращает PID лидера группы для вызывающего процесса.

group_leader(pid, leader)

Устанавливает лидера группы для данного pid в leader.

hibernate(mod, fun_name, args)

Переводит вызывающий процесс в состояние "спячки".

info(pid)

Возвращает информацию о процессе, идентифицированном pid, или возвращает nil если процесс не жив.

info(pid, spec)

Возвращает информацию о процессе, идентифицированном pid, или возвращает nil если процесс не жив.

link(pid_or_port)

Создаёт связь между вызывающим процессом и данным элементом (процессом или портом).

list()

Возвращает список PID, соответствующих всем текущим процессам на локальном узле.

monitor(item)

Начинает мониторинг данного item из вызывающего процесса.

put(key, value)

Хранит заданную пару key-value в словаре процессов.

read_timer(timer_ref)

Считывает таймер, созданный функцией send_after/3.

register(pid_or_port, name)

Регистрирует данный pid_or_port под заданным name.

registered()

Возвращает список имён, которые были зарегистрированы с помощью register/2.

send(dest, msg, options)

Отправляет сообщение на заданное dest.

send_after(dest, msg, time, opts \\ [])

Отправляет msg в dest через time миллисекунд.

sleep(timeout)

Заставляет текущий процесс заснуть на заданный timeout.

spawn(fun, opts)

Запускает заданную функцию в соответствии с заданными параметрами.

spawn(mod, fun, args, opts)

Запускает заданную функцию fun из модуля mod, передавая заданные args в соответствии с заданными параметрами.

unlink(pid_or_port)

Удаляет связь между вызывающим процессом и заданным элементом (процессом или портом).

unregister(name)

Удаляет зарегистрированное name, связанное с идентификатором PID или порта.

whereis(name)

Возвращает PID или идентификатор порта, зарегистрированные под name или nil, если имя не зарегистрировано.

Типы

dest()

dest() ::
  pid()
  | port()
  | (registered_name :: atom())
  | {registered_name :: atom(), node()}

Назначение процесса.

Удаленный или локальный PID, локальный порт, локально зарегистрированное имя или кортеж в формате {registered_name, node} для зарегистрированного имени на другом узле.

spawn_opt()

spawn_opt() ::
  :link
  | :monitor
  | {:priority, :low | :normal | :high}
  | {:fullsweep_after, non_neg_integer()}
  | {:min_heap_size, non_neg_integer()}
  | {:min_bin_vheap_size, non_neg_integer()}

spawn_opts()

spawn_opts() :: [spawn_opt()]

Функции

alive?(pid)

alive?(pid()) :: boolean()

Указывает, жив ли данный процесс на локальном узле.

Если процесс, идентифицированный pid, жив (то есть он не завершается и ещё не завершился), то эта функция возвращает true. В противном случае возвращает false.

pid должен ссылаться на процесс, работающий на локальном узле, иначе поднимается исключение ArgumentError.

Встроено компилятором.

cancel_timer(timer_ref, options \\ [])

cancel_timer(reference(), options) :: non_neg_integer() | false | :ok
when options: [async: boolean(), info: boolean()]

Отменяет таймер, возвращённый функцией send_after/3.

Если результат — целое число, оно представляет собой оставшееся время в миллисекундах до истечения таймера.

Если результат — false, таймер, соответствующий timer_ref, не найден. Это может произойти либо потому, что таймер истек, либо потому, что он уже был отменён, либо потому, что timer_ref никогда не соответствовал таймеру.

Даже если таймер истек, и сообщение было отправлено, эта функция не сообщает вам, пришло ли сообщение о таймауте к месту назначения.

Встроено компилятором.

Параметры

  • :async - (boolean) когда false, запрос на отмену является синхронным. Когда true, запрос на отмену является асинхронным, что означает, что запрос на отмену таймера отправляется и :ok возвращается сразу. По умолчанию false.

  • :info - (boolean) нужно ли возвращать информацию о том, что таймер был отменён. Когда опция :async равна false и :info равна true, возвращается целое число или false (как описано выше). Если :async равна false и :info равна false, возвращается :ok. Если :async равна true и :info равна true, вызывающему функции отправляется сообщение в формате {:cancel_timer, timer_ref, result} (где result - целое число или false как описано выше) при выполнении отмены. Если :async равна true и :info равна false, сообщение не отправляется. По умолчанию true.

delete(key)

delete(term()) :: term() | nil

Удаляет заданный key из словаря процесса.

Возвращает значение, которое находилось под key в словаре процесса, или nil если key не хранилось в словаре процесса.

Примеры

iex> Process.put(:comments, ["comment", "other comment"])
iex> Process.delete(:comments)
["comment", "other comment"]
iex> Process.delete(:comments)
nil

demonitor(monitor_ref, options \\ [])

demonitor(reference(), options :: [:flush | :info]) :: boolean()

Отключает мониторинг монитора, идентифицируемого заданным reference.

Если monitor_ref является ссылкой, полученной вызывающим процессом при вызове monitor/1, этот мониторинг отключается. Если мониторинг уже отключён, ничего не происходит.

Для получения дополнительной информации см. :erlang.demonitor/2.

Встроено компилятором.

Примеры

pid = spawn(fn -> 1 + 2 end)
ref = Process.monitor(pid)
Process.demonitor(ref)
#=> true

exit(pid, reason)

exit(pid(), term()) :: true

Отправляет сигнал выхода с заданным reason процессу pid.

Следующее поведение применяется, если reason является любым термином, кроме :normal или :kill:

  1. Если pid не перехватывает выходы, pid завершится с заданным reason.

  2. Если pid перехватывает выходы, сигнал выхода преобразуется в сообщение {:EXIT, from, reason} и передаётся в очередь сообщений pid.

Если reason является атомом :normal, pid не завершится (если только pid не является вызывающим процессом, в этом случае он завершится с причиной :normal). Если он перехватывает выходы, сигнал выхода преобразуется в сообщение {:EXIT, from, :normal} и передаётся в его очередь сообщений.

Если reason является атомом :kill, то есть, если вызвана Process.exit(pid, :kill), сигнал непрерываемого выхода отправляется процессу pid, который безусловно завершится с причиной :killed.

Встроено компилятором.

Примеры

Process.exit(pid, :kill)
#=> true

flag(flag, value)

flag(:error_handler, module()) :: module()
flag(:max_heap_size, heap_size()) :: heap_size()
flag(:message_queue_data, :erlang.message_queue_data()) ::
  :erlang.message_queue_data()
flag(:min_bin_vheap_size, non_neg_integer()) :: non_neg_integer()
flag(:min_heap_size, non_neg_integer()) :: non_neg_integer()
flag(:monitor_nodes, term()) :: term()
flag({:monitor_nodes, term()}, term()) :: term()
flag(:priority, priority_level()) :: priority_level()
flag(:save_calls, 0..10000) :: 0..10000
flag(:sensitive, boolean()) :: boolean()
flag(:trap_exit, boolean()) :: boolean()

Устанавливает заданный flag в value для вызывающего процесса.

Возвращает старое значение flag.

Для получения дополнительной информации см. :erlang.process_flag/2.

Встроено компилятором.

flag(pid, flag, value)

flag(pid(), :save_calls, 0..10000) :: 0..10000

Устанавливает заданный flag в value для заданного процесса pid.

Возвращает старое значение flag.

Выбрасывает ArgumentError, если pid не является локальным процессом.

Допустимые значения для flag — это только подмножество значений, разрешенных в flag/2, а именно :save_calls.

Для получения дополнительной информации см. :erlang.process_flag/3.

Встроено компилятором.

get()

get() :: [{term(), term()}]

Возвращает все пары ключ-значение в словаре процесса.

Встроено компилятором.

get(key, default \\ nil)

get(term(), default :: term()) :: term()

Возвращает значение для заданного key в словаре процесса, или default если key не задано.

Примеры

# Assuming :locale was not set
iex> Process.get(:locale, "pt")
"pt"
iex> Process.put(:locale, "fr")
nil
iex> Process.get(:locale, "pt")
"fr"

get_keys()

get_keys() :: [term()]

Возвращает все ключи в словаре процесса.

Встроено компилятором.

Примеры

# Assuming :locale was not set
iex> :locale in Process.get_keys()
false
iex> Process.put(:locale, "pt")
nil
iex> :locale in Process.get_keys()
true

get_keys(value)

get_keys(term()) :: [term()]

Возвращает все ключи в словаре процесса, которые имеют заданное value.

Встроено компилятором.

group_leader()

group_leader() :: pid()

Возвращает PID лидера группы для вызывающего процесса.

Встроено компилятором.

Примеры

Process.group_leader()
#=> #PID<0.53.0>

group_leader(pid, leader)

group_leader(pid(), leader :: pid()) :: true

Устанавливает лидера группы для данного pid в leader.

Обычно используется, когда процесс, запущенный из определённой оболочки, должен иметь лидера группы, отличного от :init.

Встроено компилятором.

hibernate(mod, fun_name, args)

hibernate(module(), atom(), list()) :: no_return()

Переводит вызывающий процесс в состояние «спячки».

Вызывающий процесс переводится в состояние ожидания, где его выделение памяти уменьшено по возможности, что полезно, если процесс не ожидает получить сообщения в ближайшее время.

Для получения дополнительной информации см. :erlang.hibernate/3.

Встроено компилятором.

info(pid)

info(pid()) :: keyword() | nil

Возвращает информацию о процессе, идентифицируемом pid, или возвращает nil, если процесс не активен.

Используйте только для отладки.

Для получения дополнительной информации см. :erlang.process_info/1.

info(pid, spec)

info(pid(), atom() | [atom()]) :: {atom(), term()} | [{atom(), term()}] | nil

Возвращает информацию о процессе, идентифицируемом pid, или возвращает nil, если процесс не активен.

Для получения дополнительной информации см. :erlang.process_info/2.

link(pid_or_port)

link(pid() | port()) :: true

Создаёт связь между вызывающим процессом и заданным элементом (процессом или портом).

Связи двусторонние. Связанные процессы могут быть разъединены с помощью unlink/1.

Если такая связь уже существует, эта функция ничего не делает, так как между двумя заданными процессами может быть только одна связь. Если процесс пытается создать связь с самим собой, ничего не произойдёт.

Когда два процесса связаны, каждый из них получает сигналы выхода от другого (см. также exit/2). Предположим, что pid1 и pid2 связаны. Если pid2 завершается с причиной, отличной от :normal (которая также является причиной выхода, когда процесс завершает свою работу), и pid1 не перехватывает выходы (см. flag/2), то pid1 завершится с той же причиной, что и pid2 и, в свою очередь, отправит сигнал выхода всем своим другим связанным процессам. Поведение, когда pid1 перехватывает выходы, описано в exit/2.

Для получения дополнительной информации см. :erlang.link/1.

Встроено компилятором.

list()

list() :: [pid()]

Возвращает список PID, соответствующих всем процессам, которые в настоящее время существуют на локальном узле.

Обратите внимание, что если процесс завершается, он считается существующим, но не активным. Это означает, что для такого процесса alive?/1 вернёт false, но его PID будет частью списка PID, возвращённого этой функцией.

Для получения дополнительной информации см. :erlang.processes/0.

Встроено компилятором.

Примеры

Process.list()
#=> [#PID<0.0.0>, #PID<0.1.0>, #PID<0.2.0>, #PID<0.3.0>, ...]

monitor(item)

monitor(pid() | {name, node()} | name) :: reference() when name: atom()

Начинает мониторинг заданного item из вызывающего процесса.

После завершения отслеживаемого процесса процессу-наблюдателю в виде сообщения:

{:DOWN, ref, :process, object, reason}

где:

  • ref — ссылка на монитор, возвращаемая этой функцией;
  • object — это либо pid отслеживаемого процесса (если отслеживается PID), либо {name, node} (если отслеживается удалённое или локальное имя);
  • reason — причина выхода.

Если процесс уже завершён при вызове Process.monitor/1, сообщение :DOWN доставляется немедленно.

См. необходимость мониторинга для примера. См. :erlang.monitor/2 для получения дополнительной информации.

Вставлено компилятором.

Примеры

pid = spawn(fn -> 1 + 2 end)
#=> #PID<0.118.0>
Process.monitor(pid)
#=> #Reference<0.906660723.3006791681.40191>
Process.exit(pid, :kill)
#=> true
receive do
  msg -> msg
end
#=> {:DOWN, #Reference<0.906660723.3006791681.40191>, :process, #PID<0.118.0>, :noproc}

put(key, value)

put(term(), term()) :: term() | nil

Сохраняет заданную пару key-value в словаре процесса.

Возвращаемое значение этой функции — значение, которое ранее хранилось по ключу key, или nil, если значение по этому ключу не хранилось.

Примеры

# Assuming :locale was not set
iex> Process.put(:locale, "en")
nil
iex> Process.put(:locale, "fr")
"en"

read_timer(timer_ref)

read_timer(reference()) :: non_neg_integer() | false

Считывает таймер, созданный с помощью send_after/3.

Если результат — целое число, оно представляет собой время в миллисекундах, оставшееся до истечения таймера.

Если результат — false, таймер, соответствующий timer_ref, не найден. Это может быть из-за истечения таймера, его отмены или того, что timer_ref никогда не соответствовал таймеру.

Даже если таймер истек, а сообщение было отправлено, эта функция не сообщает вам, дошло ли сообщение о таймауте до пункта назначения.

Вставлено компилятором.

register(pid_or_port, name)

register(pid() | port(), atom()) :: true

Регистрирует данный pid_or_port под данным name.

name должно быть атомом и может использоваться вместо идентификатора PID/порта при отправке сообщений с помощью Kernel.send/2.

register/2 завершится ошибкой ArgumentError в следующих случаях:

  • PID/порт не существует локально и не активен
  • имя уже зарегистрировано
  • pid_or_port уже зарегистрирован под другим name

Следующие имена зарезервированы и не могут быть назначены процессам или портам:

  • nil
  • false
  • true
  • :undefined

Примеры

Process.register(self(), :test)
#=> true
send(:test, :hello)
#=> :hello
send(:wrong_name, :hello)
#=> ** (ArgumentError) argument error

registered()

registered() :: [atom()]

Возвращает список имён, зарегистрированных с помощью register/2.

Вставлено компилятором.

Примеры

Process.register(self(), :test)
Process.registered()
#=> [:test, :elixir_config, :inet_db, ...]

send(dest, msg, options)

send(dest, msg, [option]) :: :ok | :noconnect | :nosuspend
when dest: dest(), msg: any(), option: :noconnect | :nosuspend

Отправляет сообщение указанному dest.

dest может быть удалённым или локальным PID, локальным портом, локально зарегистрированным именем или кортежем в форме {registered_name, node} для зарегистрированного имени на другом узле.

Вставлено компилятором.

Опции

  • :noconnect - при использовании, если отправка сообщения потребует автоматического подключения к другому узлу, сообщение не отправляется и возвращается :noconnect.

  • :nosuspend - при использовании, если отправка сообщения приведет к приостановке отправителя, сообщение не отправляется и возвращается :nosuspend.

В противном случае сообщение отправляется и возвращается :ok.

Примеры

iex> Process.send({:name, :node_that_does_not_exist}, :hi, [:noconnect])
:noconnect

send_after(dest, msg, time, opts \\ [])

send_after(pid() | atom(), term(), non_neg_integer(), [option]) :: reference()
when option: {:abs, boolean()}

Отправляет msg в dest через time миллисекунд.

Если dest является PID, это должен быть PID локального процесса, активного или завершённого. Если dest — атом, это должно быть имя зарегистрированного процесса, которое ищется во время доставки. Ошибка не возникает, если имя не ссылается на процесс.

Сообщение не отправляется сразу. Поэтому dest может получать другие сообщения между отправкой, даже когда time является 0.

Эта функция возвращает идентификатор таймера, который можно прочитать с помощью read_timer/1 или отменить с помощью cancel_timer/1.

Таймер будет автоматически отменён, если указанный dest — PID, который не активен, или когда указанный PID завершается. Обратите внимание, что таймеры не будут автоматически отменены, когда dest — атом (так как разрешение атома выполняется при доставке).

Вставлено компилятором.

Опции

  • :abs - (логическое значение) когда false, time рассматривается как относительное к текущему монотонному времени. Когда true, time — абсолютное значение эрланговского монотонного времени, в которое msg должен быть доставлен dest. Чтобы узнать больше о монотонном времени Erlang и других связанных с временем понятиях, см. документацию для модуля System. По умолчанию false.

Примеры

timer_ref = Process.send_after(pid, :hi, 1000)

sleep(timeout)

sleep(timeout()) :: :ok

Процесс спит заданное timeout.

timeout — это либо количество миллисекунд сна в виде целого числа, либо атом :infinity. Когда :infinity указан, текущий процесс спит вечно и не потребляет или не отвечает на сообщения.

Используйте эту функцию с большой осторожностью. Почти во всех ситуациях, где вы бы использовали sleep/1 в Elixir, скорее всего, существует более правильный, быстрый и точный способ достижения того же с помощью обмена сообщениями.

Например, если вы ждёте, что процесс выполнит некоторое действие, лучше передавать прогресс этого действия с помощью сообщений.

Другими словами, не:

Task.start_link(fn ->
  do_something()
  ...
end)

# Wait until work is done
Process.sleep(2000)

А делайте:

parent = self()

Task.start_link(fn ->
  do_something()
  send(parent, :work_is_done)
  ...
end)

receive do
  :work_is_done -> :ok
after
  # Optional timeout
  30_000 -> :timeout
end

В таких случаях, как выше, предпочтительнее использовать Task.async/1 и Task.await/2.

Аналогично, если вы ждёте завершения процесса, отслеживайте этот процесс вместо сна. Не:

Task.start_link(fn ->
  ...
end)

# Wait until task terminates
Process.sleep(2000)

А делайте:

{:ok, pid} =
  Task.start_link(fn ->
    ...
  end)

ref = Process.monitor(pid)

receive do
  {:DOWN, ^ref, _, _, _} -> :task_is_down
after
  # Optional timeout
  30_000 -> :timeout
end

spawn(fun, opts)

spawn((() -> any()), spawn_opts()) :: pid() | {pid(), reference()}

Запускает данную функцию в соответствии с заданными параметрами.

Результат зависит от заданных параметров. В частности, если :monitor задан в качестве параметра, он вернёт кортеж, содержащий PID и ссылку на мониторинг, в противном случае только PID запущенного процесса.

Дополнительные параметры доступны; для получения полного списка доступных параметров см. :erlang.spawn_opt/4.

Вставлено компилятором.

Примеры

Process.spawn(fn -> 1 + 2 end, [:monitor])
#=> {#PID<0.93.0>, #Reference<0.18808174.1939079169.202418>}
Process.spawn(fn -> 1 + 2 end, [:link])
#=> #PID<0.95.0>

spawn(mod, fun, args, opts)

spawn(module(), atom(), list(), spawn_opts()) :: pid() | {pid(), reference()}

Запускает указанную функцию fun из модуля mod, передавая указанные args в соответствии с заданными параметрами.

Результат зависит от заданных параметров. В частности, если :monitor задан в качестве параметра, он вернёт кортеж, содержащий PID и ссылку на мониторинг, в противном случае только PID запущенного процесса.

Также принимаются дополнительные параметры; для получения списка доступных параметров см. :erlang.spawn_opt/4.

Вставлено компилятором.

unlink(pid_or_port)

unlink(pid() | port()) :: true

Удаляет связь между вызывающим процессом и заданным элементом (процессом или портом).

Если такой связи нет, эта функция ничего не делает. Если pid_or_port не существует, эта функция не генерирует ошибок и просто ничего не делает.

Возвращаемое значение этой функции всегда true.

См. :erlang.unlink/1 для получения дополнительной информации.

Вставлено компилятором.

unregister(name)

unregister(atom()) :: true

Удаляет зарегистрированное name, связанное с идентификатором PID или порта.

Возвращает ошибку ArgumentError, если имя не зарегистрировано ни для какого PID или порта.

Вставлено компилятором.

Примеры

Process.register(self(), :test)
#=> true
Process.unregister(:test)
#=> true
Process.unregister(:wrong_name)
#=> ** (ArgumentError) argument error

whereis(name)

whereis(atom()) :: pid() | port() | nil

Возвращает идентификатор PID или порта, зарегистрированный под name, или nil, если имя не зарегистрировано.

См. :erlang.whereis/1 для получения дополнительной информации.

Примеры

Process.register(self(), :test)
Process.whereis(:test)
#=> #PID<0.84.0>
Process.whereis(:wrong_name)
#=> nil

© 2012 Plataformatec
Licensed under the Apache License, Version 2.0.
https://hexdocs.pm/elixir/1.8.2/Process.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API