Extended process registry This module implements an extended process registry.
Behaviours: gen_server
.
Authors: Ulf Wiger (ulf@wiger.net
).
For a detailed description, see erlang07-wiger.pdf.
NOTE: The functions in the Gproc API expect the Gproc application to be running.
Gproc relies on a central server and an ordered-set ets table.
Effort is made to perform as much work as possible in the client without
sacrificing consistency. A few things can be tuned by setting the following
application environment variables in the top application of gproc
(usually gproc
):
{ets_options, list()}
- Currently, the options {write_concurrency, F}
and {read_concurrency, F}
are allowed. The default is
[{write_concurrency, true}, {read_concurrency, true}]
{server_options, list()}
- These will be passed as spawn options when
starting the gproc
and gproc_dist
servers. Default is []
. It is
likely that {priority, high | max}
and/or increasing min_heap_size
will improve performance.
context() = {scope(), type()} | type()
ctr_incr() = integer()
ctr_setval() = integer()
ctr_thr() = integer()
ctr_update() = ctr_incr() | {ctr_incr(), ctr_thr(), ctr_setval()}
headpat() = {keypat(), pidpat(), any()}
increment() = ctr_incr() | ctr_update() | [ctr_update()]
key() = {type(), scope(), any()}
keypat() = {sel_type() | sel_var(), l | g | sel_var(), any()}
monitor_type() = info | standby | follow
pidpat() = pid() | sel_var()
reg_id() = {type(), scope(), any()}
scope() = l | g
sel_context() = {scope(), type()} | type()
sel_pattern() = [{headpat(), list(), list()}]
sel_scope() = scope | all | global | local
sel_type() = type() | names | props | counters | aggr_counters | resources | resource_counters
sel_var() = '_' | atom()
type() = n | p | c | a | r | rc
unique_id() = {n | a, scope(), any()}
value() = any()
add_global_aggr_counter/1 | Registers a global (unique) aggregated counter. |
add_global_counter/2 | Registers a global (non-unique) counter. |
add_global_name/1 | Registers a global (unique) name. |
add_global_property/2 | Registers a global (non-unique) property. |
add_local_aggr_counter/1 | Registers a local (unique) aggregated counter. |
add_local_counter/2 | Registers a local (non-unique) counter. |
add_local_name/1 | Registers a local (unique) name. |
add_local_property/2 | Registers a local (non-unique) property. |
add_shared_local_counter/2 | Registers a local shared (unique) counter. |
audit_process/1 | |
await/1 | Equivalent to await(Key, infinity). |
await/2 | Wait for a name or aggregated counter to be registered. |
await/3 | Wait for a name or aggregated counter to be registered on Node . |
bcast/2 | Equivalent to bcast(nodes(), Key, Msg). |
bcast/3 | Sends a message to processes corresponding to Key on Nodes. |
cancel_wait/2 | Cancels a previous call to nb_wait/1. |
cancel_wait/3 | Cancels a previous call to nb_wait/2. |
cancel_wait_or_monitor/1 | |
default/1 | |
demonitor/2 | Remove a monitor on a registered name This function is the reverse of monitor/1. |
ensure_reg/1 | Equivalent to ensure_reg(Key, default(Key), []). |
ensure_reg/2 | Equivalent to ensure_reg(Key, Value, []). |
ensure_reg/3 | Registers a new name or property unless such and entry (by key) has already been registered by the current process. |
ensure_reg_other/2 | |
ensure_reg_other/3 | Equivalent to ensure_reg_other(Key, Pid, Value, []). |
ensure_reg_other/4 | Register or update name or property to another process. |
first/1 | Behaves as ets:first(Tab) for a given type of registration. |
get_attribute/2 | Get attribute value of Attr associated with Key for most likely Pid. |
get_attribute/3 | Get the attribute value of Attr associated with Key for process Pid. |
get_attribute_shared/2 | Get the attribute value of Attr associated with the shared Key . |
get_attributes/1 | Get attributes associated with registration. |
get_attributes/2 | Returns the list of attributes associated with the registration. |
get_env/3 | Equivalent to get_env(Scope, App, Key, [app_env]). |
get_env/4 | Read an environment value, potentially cached as a gproc_env property. |
get_set_env/3 | Equivalent to get_set_env(Scope, App, Key, [app_env]). |
get_set_env/4 | Fetch and cache an environment value, if not already cached. |
get_value/1 | Reads the value stored with a key registered to the current process. |
get_value/2 | Reads the value stored with a key registered to the process Pid. |
get_value_shared/1 | Reads the value stored with a shared key. |
give_away/2 | Atomically transfers the key From to the process identified by To . |
goodbye/0 | Unregister all items of the calling process and inform gproc to forget about the calling process. |
i/0 | Similar to the built-in shell command i() but inserts information
about names and properties registered in Gproc, where applicable. |
info/1 | Similar to process_info(Pid) but with additional gproc info. |
info/2 | Similar to process_info(Pid, Item), but with additional gproc info. |
last/1 | Behaves as ets:last(Tab) for a given type of registration. |
lookup_global_aggr_counter/1 | Lookup a global (unique) aggregated counter and returns its value. |
lookup_global_counters/1 | Look up all global (non-unique) instances of a given Counter. |
lookup_global_name/1 | Lookup a global unique name. |
lookup_global_properties/1 | Look up all global (non-unique) instances of a given Property. |
lookup_local_aggr_counter/1 | Lookup a local (unique) aggregated counter and returns its value. |
lookup_local_counters/1 | Look up all local (non-unique) instances of a given Counter. |
lookup_local_name/1 | Lookup a local unique name. |
lookup_local_properties/1 | Look up all local (non-unique) instances of a given Property. |
lookup_pid/1 | Lookup the Pid stored with a key. |
lookup_pids/1 | Returns a list of pids with the published key Key. |
lookup_value/1 | Lookup the value stored with a key. |
lookup_values/1 | Retrieve the {Pid,Value} pairs corresponding to Key. |
monitor/1 | Equivalent to monitor(Key, info). |
monitor/2 | monitor a registered name
monitor(Key, info) works much like erlang:monitor(process, Pid), but monitors
a unique name registered via gproc. |
mreg/3 | Register multiple {Key,Value} pairs of a given type and scope. |
munreg/3 | Unregister multiple Key items of a given type and scope. |
nb_wait/1 | Wait for a name or aggregated counter to be registered. |
nb_wait/2 | Wait for a name or aggregated counter to be registered on Node . |
next/2 | Behaves as ets:next(Tab,Key) for a given type of registration. |
prev/2 | Behaves as ets:prev(Tab,Key) for a given type of registration. |
reg/1 | Equivalent to reg(Key, default(Key), []). |
reg/2 | Register a name or property for the current process. |
reg/3 | Register a name or property for the current process
Attrs (default: [] ) can be inspected using get_attribute/2 . |
reg_or_locate/1 | Equivalent to reg_or_locate(Key, default(Key)). |
reg_or_locate/2 | Try registering a unique name, or return existing registration. |
reg_or_locate/3 | Spawn a process with a registered name, or return existing registration. |
reg_other/2 | Equivalent to reg_other(Key, Pid, default(Key), []). |
reg_other/3 | Equivalent to reg_other(Key, Pid, Value, []). |
reg_other/4 | Register name or property to another process. |
reg_shared/1 | Register a resource, but don't tie it to a particular process. |
reg_shared/2 | Register a resource, but don't tie it to a particular process. |
reg_shared/3 | |
register_name/2 | Behaviour support callback. |
reset_counter/1 | Reads and resets a counter in a "thread-safe" way. |
select/1 | Perform a select operation on the process registry. |
select/2 | Perform a select operation with limited context on the process registry. |
select/3 | Like select/2 but returns Limit objects at a time. |
select_count/1 | Equivalent to select_count(all, Pat). |
select_count/2 | Perform a select_count operation on the process registry. |
send/2 | Sends a message to the process, or processes, corresponding to Key. |
set_attributes/2 | Add/modify {Key, Value} attributes associated with a registration. |
set_attributes_shared/2 | Add/modify {Key, Value} attributes associated with a shared registration. |
set_env/5 | Updates the cached value as well as underlying environment. |
set_value/2 | Sets the value of the registration given by Key. |
set_value_shared/2 | Sets the value of the shared registration given by Key. |
start_link/0 | Starts the gproc server. |
table/0 | Equivalent to table({all, all}). |
table/1 | Equivalent to table(Context, []). |
table/2 | QLC table generator for the gproc registry. |
unreg/1 | Unregister a name or property. |
unreg_other/2 | Unregister a name registered to another process. |
unreg_shared/1 | Unregister a shared resource. |
unregister_name/1 | Equivalent to unreg / 1. |
update_counter/2 | Updates the counter registered as Key for the current process. |
update_counter/3 | |
update_counters/2 | Update a list of counters. |
update_shared_counter/2 | Updates the shared counter registered as Key. |
where/1 | Returns the pid registered as Key. |
whereis_name/1 | Equivalent to where / 1. |
wide_await/3 | Wait for a local name to be registered on any of Nodes . |
add_global_aggr_counter(Name) -> any()
Equivalent to reg({a, g, Name})
.
Registers a global (unique) aggregated counter.
add_global_counter(Name, Initial) -> any()
Registers a global (non-unique) counter. @equiv reg({c,g,Name},Value)
add_global_name(Name) -> any()
Registers a global (unique) name. @equiv reg({n,g,Name})
add_global_property(Name, Value) -> any()
Registers a global (non-unique) property. @equiv reg({p,g,Name},Value)
add_local_aggr_counter(Name) -> any()
Equivalent to reg({a, l, Name})
.
Registers a local (unique) aggregated counter.
add_local_counter(Name, Initial) -> any()
Registers a local (non-unique) counter. @equiv reg({c,l,Name},Value)
add_local_name(Name) -> any()
Registers a local (unique) name. @equiv reg({n,l,Name})
add_local_property(Name, Value) -> any()
Registers a local (non-unique) property. @equiv reg({p,l,Name},Value)
add_shared_local_counter(Name, Initial) -> any()
Equivalent to reg_shared({c, l, Name}, Value)
.
Registers a local shared (unique) counter.
audit_process(Pid::pid()) -> ok
await(Key::key()) -> {pid(), Value}
await(Key::key(), Timeout) -> {pid(), Value}
Timeout = integer() | infinity
Wait for a name or aggregated counter to be registered. The function raises an exception if the timeout expires. Timeout must be either an integer > 0 or 'infinity'. A small optimization: we first perform a lookup, to see if the name is already registered. This way, the cost of the operation will be roughly the same as of where/1 in the case where the name is already registered (the difference: await/2 also returns the value).
await(Node::node(), Key::key(), Timeout) -> {pid(), Value}
Timeout = integer() | infinity
Wait for a name or aggregated counter to be registered on Node
.
This function works exactly like await/2
, but queries a remote
node instead. An exception is thrown if Node
cannot be reached. If gproc
is not running on a given node, this is treated the same as the node being
down.
bcast(Key::key(), Msg::any()) -> Msg
bcast(Nodes::[atom()], Key::key(), Msg::any()) -> Msg
cancel_wait(Key::key(), Ref) -> ok
Ref = all | reference()
Cancels a previous call to nb_wait/1
If Ref = all
, all wait requests on Key
from the calling process
are canceled.
cancel_wait(Node::node(), Key::key(), Ref) -> ok
Ref = all | reference()
Cancels a previous call to nb_wait/2
This function works just like cancel_wait/2
, but talks to a remote
node.
cancel_wait_or_monitor(Key) -> any()
default(X1) -> any()
demonitor(Key::key(), Ref::reference()) -> ok
ensure_reg(Key::key(), Value::value()) -> new | updated
ensure_reg(Key::key(), Value::value(), Attrs::attrs()) -> new | updated
ensure_reg_other(Key::key(), Pid::pid(), Value::value(), Attrs::attrs()) -> new | updated
first(Context::context()) -> key() | '$end_of_table'
get_attribute(Key, Attribute::atom()) -> Value
get_attribute(Key, Pid::pid() | shared, Attr::atom()) -> Value
get_attribute_shared(Key, Attr::atom()) -> Value
get_attributes(Key::key()) -> [{K, V}]
get_attributes(Key::key(), Pid::pid() | shared) -> [{K, V}]
get_env(Scope::scope(), App::atom(), Key::atom()) -> term()
get_env(Scope::scope(), App::atom(), Key::atom(), Strategy) -> term()
Strategy = [Alternative]
Alternative = app_env | os_env | inherit | {inherit, pid()} | {inherit, unique_id()} | init_arg | {mnesia, ActivityType, Oid, Pos} | {default, term()} | error
Read an environment value, potentially cached as a gproc_env
property.
This function first tries to read the value of a cached property,
{p, Scope, {gproc_env, App, Key}}
. If this fails, it will try the provided
alternative strategy. Strategy
is a list of alternatives, tried in order.
Each alternative can be one of:
app_env
- try application:get_env(App, Key)
os_env
- try os:getenv(ENV)
, where ENV
is Key
converted into an
uppercase string{os_env, ENV}
- try os:getenv(ENV)
inherit
- inherit the cached value, if any, held by the parent process.{inherit, Pid}
- inherit the cached value, if any, held by Pid
.{inherit, Id}
- inherit the cached value, if any, held by the process
registered in gproc
as Id
.init_arg
- try init:get_argument(Key)
; expects a single value, if any.{mnesia, ActivityType, Oid, Pos}
- try
mnesia:activity(ActivityType, fun() -> mnesia:read(Oid) end)
; retrieve
the value in position Pos
if object found.{default, Value}
- set a default value to return once alternatives have
been exhausted; if not set, undefined
will be returned.error
- raise an exception, erlang:error(gproc_env, [App, Key, Scope])
.While any alternative can occur more than once, the only one that might make
sense to use multiple times is {default, Value}
.
The return value will be one of:
error
exception,
whichever comes first{default, Value}
, or undefined
, if there is no
matching alternative, default or error
entry in the list.The error
option can be used to assert that a value has been previously
cached. Alternatively, it can be used to assert that a value is either cached
or at least defined somewhere,
e.g. get_env(l, mnesia, dir, [app_env, error])
.
get_set_env(Scope::scope(), App::atom(), Key::atom()) -> term()
get_set_env(Scope::scope(), App::atom(), Key::atom(), Strategy) -> Value
get_value(Key) -> Value
get_value(Key, Pid) -> Value
get_value_shared(Key) -> Value
give_away(From::key(), To::pid() | key()) -> undefined | pid()
goodbye() -> ok
i() -> ok
info(Pid::pid()) -> ProcessInfo
ProcessInfo = [{gproc, [{Key, Value}]} | ProcessInfo]
Similar to process_info(Pid)
but with additional gproc info.
Returns the same information as process_info(Pid), but with the
addition of a gproc
information item, containing the {Key,Value}
pairs registered to the process.
info(Pid::pid(), Item::atom()) -> {Item, Info}
last(Context::context()) -> key() | '$end_of_table'
lookup_global_aggr_counter(Name::any()) -> integer()
lookup_global_counters(Counter::any()) -> [{pid(), Value::integer()}]
lookup_global_name(Name::any()) -> pid()
lookup_global_properties(Property::any()) -> [{pid(), Value}]
lookup_local_aggr_counter(Name::any()) -> integer()
lookup_local_counters(Counter::any()) -> [{pid(), Value::integer()}]
lookup_local_name(Name::any()) -> pid()
lookup_local_properties(Property::any()) -> [{pid(), Value}]
lookup_pid(Key) -> Pid
lookup_pids(Key::key()) -> [pid()]
lookup_value(Key) -> Value
lookup_values(Key::key()) -> [{pid(), Value}]
monitor(Key::key(), Type::monitor_type()) -> reference()
mreg(T::type(), C::scope(), KVL::[{Key::any(), Value::any()}]) -> true
munreg(T::type(), C::scope(), L::[Key::any()]) -> true
nb_wait(Key::key()) -> Ref
nb_wait(Node::node(), Key::key()) -> Ref
next(Context::context(), Key::key()) -> key() | '$end_of_table'
prev(Context::context(), Key::key()) -> key() | '$end_of_table'
reg(Key::key()) -> true
reg(Key::key(), Value::value()) -> true
reg(Key::key(), Value::value(), Attrs::attrs()) -> true
reg_or_locate(Key::key()) -> {pid(), NewValue}
reg_or_locate(Key::key(), Value) -> {pid(), NewValue}
reg_or_locate(Key::key(), Value, Fun::function()) -> {pid(), NewValue}
reg_other(Key, Pid, Value, Attrs) -> true
reg_shared(Key::key()) -> true
reg_shared(Key::key(), Value) -> true
register_name(Name::key(), Pid::pid()) -> yes | no
reset_counter(Key) -> {ValueBefore, ValueAfter}
Key = {c, Scope, Name} | {n, Scope, Name}
Scope = l | g
ValueBefore = integer()
ValueAfter = integer()
Reads and resets a counter in a "thread-safe" way
This function reads the current value of a counter and then resets it to its
initial value. The reset operation is done using update_counter/2
,
which allows for concurrent calls to update_counter/2
without losing
updates. Aggregated counters are updated accordingly.
If Key
refers to a unique name, the operation will depend on the value
part of the registration being an integer(). While non-integer values are
not permitted at all for counter objects, it is the user's responsibility to
ensure that a name, on which reset_counter/1
is to be performed, has the
appropriate value type.
select(Continuation::Arg) -> [Match] | {[Match], Continuation} | '$end_of_table'
Arg = Continuation | sel_pattern()
Match = {Key, Pid, Value}
Perform a select operation on the process registry
When Arg = Contination, resume a gproc:select/1 operation (see ets:select/1
When Arg = sel_pattern()
, this function executes a select operation,
emulating ets:select/1
select/2
offers the opportunity to narrow the search
(by limiting to only global or local scope, or a single type of object).
When only a pattern as single argument is given, both global and local scope,
as well as all types of object can be searched. Note that the pattern may
still limit the select operation so that scanning the entire table is avoided.
The physical representation in the registry may differ from the above,
but the select patterns are transformed appropriately. The logical
representation for the gproc select operations is given by
headpat()
.
select(Context::sel_context(), Pat::sel_pattern()) -> [{Key, Pid, Value}]
select(Context::context(), Pat::sel_patten(), Limit::integer()) -> {[Match], Continuation} | '$end_of_table'
select_count(Pat::sel_pattern()) -> [sel_object()]
select_count(Context::context(), Pat::sel_pattern()) -> [{Key, Pid, Value}]
send(Key::process() | key(), Msg::any()) -> Msg
set_attributes(Key::key(), Props::[{atom(), any()}]) -> true
set_attributes_shared(Key::key(), Props::[{K, V}]) -> true
set_env(Scope::scope(), App::atom(), Key::atom(), Value::term(), Strategy) -> Value
Strategy = [Alternative]
Alternative = app_env | os_env | {os_env, VAR} | {mnesia, ActivityType, Oid, Pos}
Updates the cached value as well as underlying environment.
This function should be exercised with caution, as it affects the larger environment outside gproc. This function modifies the cached value, and then proceeds to update the underlying environment (OS environment variable or application environment variable).
When the mnesia
alternative is used, gproc will try to update any existing
object, changing only the Pos
position. If no such object exists, it will
create a new object, setting any other attributes (except Pos
and the key)
to undefined
.
set_value(Key::key(), Value) -> true
set_value_shared(Key::key(), Value) -> true
start_link() -> {ok, pid()}
table() -> any()
table(Context::context()) -> any()
table(Context::context(), Opts) -> any()
unreg(Key::key()) -> true
unreg_other(Key::key(), Pid::pid()) -> true
unreg_shared(Key::key()) -> true
update_counter(Key::key(), Incr::increment()) -> integer()
update_counters(X1::scope(), Cs::[{key(), pid(), increment()}]) -> [{key(), pid(), integer()}]
update_shared_counter(Key::key(), Incr) -> integer() | [integer()]
Incr = IncrVal | UpdateOp | [UpdateOp]
UpdateOp = IncrVal | {IncrVal, Threshold, SetValue}
IncrVal = integer()
Updates the shared counter registered as Key.
This function works almost exactly like ets:update_counter/3
(see http://www.erlang.org/doc/man/ets.html#update_counter-3
), but
will fail if the type of object referred to by Key is not a counter.
Aggregated counters with the same name will be updated automatically.
The UpdateOp
patterns are the same as for ets:update_counter/3
, except
that the position is omitted; in gproc, the value position is always 3
.
where(Key::key()) -> pid() | undefined
wide_await(Nodes::[node()], Key::key(), Timeout) -> {pid(), Value}
Timeout = integer() | infinity
Wait for a local name to be registered on any of Nodes
.
This function works rather like await/2
, but queries all nodes in
the Nodes
list at the same time. The first node to respond with a
process registered as Key
will provide the result. Other results are
ignored. Key
must be a unique name with local scope, i.e. {n,l,Name}
.
An exception is thrown upon timeout, or if no node can be reached (if gproc is not running on a given node, this is treated the same as the node being down).