Copyright © Ericsson AB 2005 All rights reserved. The information in this document is the property of Ericsson. Except as specifically authorized in writing by Ericsson, the receiver of this document shall keep the information contained herein confidential and shall protect the same in whole or in part from disclosure and dissemination to third parties. Disclosure and disseminations to the receivers employees shall only be made on a strict need to know basis.
Behaviours: gen_server.
Flexible Local Process Registry
This application supports local registration of processes using any erlang term. Furthermore, each process can register by several different names at the same time.
proc
works with unique names
and
non-unique properties
.
A name can be any erlang term
(except a pid or '_'), and each process can register itself under many
different unique names.
A property
can be any term (except '_'), and must be unique
within a process, but several processes can register the same
property.
Furthermore, there are "fold" and "select" functions to allow for efficient iteration over names or properties in the process registry.
Many of the operations to access names and properties rely on
the semantics given by //stdlib/ets
, and this is often
mentioned in the interface documentation. This means that it is
safe to assume that the functions conform to the search semantics
of ordered_set ets tables. However, it is not safe to assume
anything about whether the data in fact resides in ets tables, and
if so, what those tables are called, or indeed how the data is
represented internally.
add_counter/2 | Publish a counter property for the current process. |
add_counter/3 | Publish a counter property on behalf of Process . |
add_property/1 | Publish a property of the current process. |
add_property/2 | Publish a property on behalf of another process. |
await_reg/1 | Request to be notified when someone registers as Name . |
clear_await_reg/1 | Cancel waiting for notification of process registration of a given name. |
del_counter/1 | Un-publish a counter property for the current process. |
del_counter/2 | Un-publish a counter property on behalf of Process . |
del_property/1 | Un-publishes the property Property for the current process. |
del_property/2 | Un-publish the property Property on behalf of Process . |
enable_i/0 | |
first/1 | Analogous to ets:first/1 . |
fold_names/3 | Similar to lists:foldl/3 , but based on a list of select
patterns, identifying a sub-set of unique names. |
fold_names/4 | Like fold_names/3 , but works in batches of Limit objects
at a time, in order to improve memory characteristics. |
fold_names/5 | Like fold_names/4 , but applies a "Regulator function"
after each batch of objects before proceeding with the next one. |
fold_properties/3 | Similar to //stdlib/lists:foldl/3 , but based on a
select pattern on Property , identifying a sub-set of
published properties. |
fold_properties/4 | Like fold_properties/3 , but works in batches of Limit
objects at a time, in order to improve raw performance. |
fold_properties/5 | Like fold_properties/4 , but applies a "Regulator function"
after each batch of objects before proceeding with the next one. |
guards/1 | Expand a list of select guards, allowing for the pseudo guard
is_counter . |
i/1 | Like c:i/0 , but allows for filtering output with
proc names and properties. |
info/1 | Like process_info(PidOfProcess) , but with added
proc-related attributes. |
info/2 | Like process_info(PidOfProcess, Attr) but accepts some
additional attributes. |
is_counter/1 | Check whether Property is a counter property. |
is_counter/2 | Check whether Propery registered under Process is a counter
property. |
is_property/1 | Returns true if Property is a published property of the current
process. |
is_property/2 | Check whether Property is in fact a property registered with Process. |
last/1 | Analogous to ets:last/1 . |
next/2 | Analogous to ets:next/2 . |
pids/1 | Returns all pids for which a property Property is published. |
pids/2 | Similar to pids/1 , but also allowing select guards. |
previous/2 | Analogous to ets:previous/2 . |
properties_by_pid/1 | Lists all properties for a given process. |
properties_by_pid/2 | Lists all properties for a given process that match the pattern KeyPat. |
properties_by_pid/3 | Like properties_by_pid/2 , but with an added list of guards. |
read_counter/1 | Read the value of a counter property for the current process. |
read_counter/2 | Read the value of a counter property published by Process . |
reg/1 | Register a unique Name . |
replace_property/2 | Equivalent to del_property(OldProperty), add_property(NewProperty), but much more efficient. |
replace_property/3 | Replace OldProperty with NewProperty on behalf of Process . |
select/1 | Analogous to ets:select/1 . |
select_fold_properties/3 | Like fold_properties/3 but more flexible as it allows
for combining several patterns into one query. |
select_fold_properties/4 | Like select_fold_properties/3 , but works in batches of Limit
objects at a time, in order to improve raw performance. |
select_fold_properties/5 | Like select_fold_properties/4 , but applies a
"Regulator function"
after each batch of objects before proceeding with the next one. |
select_names/1 | Returns {Name,Pid} objects one at a time based on
a given selection of all registered unique names. |
select_names/2 | Like select_names/1 , but works in batches of Limit
objects at a time, in order to improve raw performance. |
select_pattern/1 | Helper function to generate select patterns from the more
intuitive patterns Property (or Name , as it works equally for names). |
select_pattern/2 | As select_pattern/1 , but with the option to add Guard
expressions. |
select_properties/1 | Returns {Property,Pid} objects one at a time based on
a given selection of all registered instances of Key . |
select_properties/2 | Like select_properties/1 but works in batches of Limit
objects at a time in order to improve raw performance. |
send/2 | Analogous to Name ! Msg , except that send({Node,Dest}, Msg)
will be interpreted as 'send to the local process registered as
{Node, Dest}'. |
set_access/1 | Control the ability of Processes to perform certain functions on behalf of the current process. |
start_link/0 | Starts the proc server. |
unreg/1 | Unregister Name . |
update_counter/2 | Update the counter attribute of a counter property. |
update_counter/3 | Update counter attribute on behalf of Process . |
where/1 | Analogous to erlang:whereis(Name) . |
add_counter(Name, InitialValue::integer()) -> true
Publish a counter property for the current process.
Counter properties behave as normal properties with the following exceptions:
update_counter/2
replace_property/2
add_counter(Process, Name, InitialValue::integer()) -> true
Publish a counter property on behalf of Process
.
This function is allowed only if permission to add counters
has been given through Process
calling grant_access/2
.
If permission to add counters has not been given, this function
exits with access
.
add_property(Property::term()) -> true
Publish a property of the current process.
If Property
is already published for the current process,
this function exits with badarg.
This operation can be viewed as publishing the meta-data Property
as part of the interface of the process. Several processes may publish
the same property. The process can be found (as part of a group)
through this property, using one of the functions fold_properties/3
, pids/1
, et al.
add_property(Process, Property) -> true
Publish a property on behalf of another process.
Adding properties on behalf of another process is only
allowed if the other process has called set_access/1
,
giving this process the proper rights to act as proxy.
Process
can be either a pid()
or a registered name.
await_reg(Pid::Name) -> {already_registered, pid()} | Reg
Request to be notified when someone registers as Name
.
If Name
is already registered, the function returns
with the value {already_registered, Pid}
. Otherwise, it returns
a "reference" (not necessarily of type reference()
) that can be used
to recognize a future message.
When some process P
registers as Name
, a message on the form
{sysProgReg, Ref, reg, Name, Pid}
is sent to each waiting process
(note that Ref will be different for each waiting process.)
clear_await_reg(Ref) -> true
Cancel waiting for notification of process registration of a given name.
This function exits with badarg
if Ref does not appear to be
a valid reference returned by await_reg/1
; otherwise returns
true
.
del_counter(Name) -> true
Un-publish a counter property for the current process.
del_counter(Process, Name) -> true
Un-publish a counter property on behalf of Process
.
This function is allowed only if permission to delete counters
has been given through Process
calling grant_access/2
.
If permission to delete counters has not been given, this function
exits with access
.
del_property(Property) -> true
Un-publishes the property Property
for the current process.
If there is no published property Property
(see add_property/1
), for the current process, the function
exits with badarg
.
del_property(Process, Property) -> true
Un-publish the property Property
on behalf of Process
.
This function is allowed only if permission to delete properties
has been given through Process
calling grant_access/2
.
If permission to delete properties has not been given, this function
exits with access
.
first(Type::names | properties) -> Key | '$end_of_table'
Analogous to ets:first/1
.
The tables corresponding to names
and properties
both have
ordered_set
semantics.
fold_names(Fun::function(), Acc, Patterns) -> NewAcc
Similar to lists:foldl/3
, but based on a list of select
patterns, identifying a sub-set of unique names.
For each matching name, a call is made to
Fun({Name1,Pid1}, Acc1), which is expected to return
NewAcc
.
Patterns
is a list of match specifications on the same form as
that used by ets:select_delete/2
and ets:select_count/2
,
that is:
* Patterns = [MatchFunction] | '_' * MatchFunction = {MatchHead, [Guard], [Result]} * MatchHead = "Pattern as in ets:match" * Guard = {"Guardtest name", ...} * Result = true (if object is to be included)
The following expression would return a list of all registered unique names together with the processes that registered them:
proc:fold_names(fun(X,Acc) -> [X|Acc] end, [], [{'_',[],[true]}])
For convenience, the special pattern '_' is also allowed. It is
expanded to [{'_',[],[true]}]
.
This function is equivalent to fold_names(Fun,Acc,Patterns,100)
,
(see fold_names/5
.)
fold_names(Fun, Acc, Patterns, Limit::integer()) -> NewAcc
Like fold_names/3
, but works in batches of Limit
objects
at a time, in order to improve memory characteristics.
fold_names/3
uses a default limit of 1 object at a time.
This function is equivalent to
fold_names(Fun,Acc,Patterns,Limit,fun(_) -> true end)
,
(see fold_names/5
.)
fold_names(Fun::function(), Acc, Patterns, Limit::integer(), Regulator::function()) -> NewAcc
Like fold_names/4
, but applies a "Regulator function"
after each batch of objects before proceeding with the next one.
The Regulator
function is expected to take the current accumulator
as an argument and return either true
(in which case processing
continues), or false
(in which case the fold_names/5
function breaks
and returns the current accumulator.
fold_properties(Fun::function(), Acc, Property) -> NewAcc
Similar to //stdlib/lists:foldl/3
, but based on a
select pattern on Property
, identifying a sub-set of
published properties.
For each matching key, a call is made to
Fun({Property1,Pid1}, Acc1), which is expected to return
NewAcc
. Note that, as in pids/1
, Property
can be select a pattern. The following expression would return a
list of all published instances of Property
together with the processes
that registered them:
proc:fold_properties(fun(X,Acc) -> [X|Acc] end, [], '_')
This function is equivalent to fold_properties(Fun,Acc,Property,1)
,
(see fold_properties/4
.) See also select_pattern/1
.
fold_properties(Fun::function(), Acc, Properties::Key, Limit::integer()) -> NewAcc
Like fold_properties/3
, but works in batches of Limit
objects at a time, in order to improve raw performance.
fold_properties/3
uses a default limit of 1 object at a time.
This function is equivalent to
fold_properties(Fun,Acc,Property,Limit,fun(_) -> true end)
,
(see fold_properties/5
.) See also select_pattern/1
.
fold_properties(Fun::function(), Acc, Property, Limit::integer(), Regulator::function()) -> NewAcc
Like fold_properties/4
, but applies a "Regulator function"
after each batch of objects before proceeding with the next one.
The Regulator
function is expected to take the current accumulator
as an argument and return either true
(in which case processing
continues), or false
(in which case the fold_properties/5
function
breaks and returns the current accumulator. See also
select_pattern/1
.
guards(Gs::List) -> NewList
Expand a list of select
guards, allowing for the pseudo guard
is_counter
.
How counter properties can be distinguished from regular properties
internally is not defined in the proc interface. Using this function,
it is however possible to specify a guard test, is_counter
, which will
expand to a legal guard. The is_counter
test can be combined with the
standard logical operators, not
, and
, or
, orelse
, andalso
,
and xor
.
Example:
proc:select_properties( [{'_', proc:guards([{'not', is_counter}]), [true]}]).
will list all published properties that are not counters.
i(Options::Option) -> ok
Like c:i/0
, but allows for filtering output with
proc
names and properties.
Usage: i([{i | x, names | properties, Patterns}])
.
calls c:i(Processes)
for a subset of all running processes.
{i, Type, Pattern}
specifies by name or property which processes
to include. {x, Type, Pattern}
specifies which processes to
exclude from the listing. If no {i,T,P}
tuples are specified,
all processes are included per default, then reduced by the
{x,T,P}
patterns. Multiple tuples are allowed.
Pattern
is a match specification where the result head is true
.
Note that currently, using ets:fun2ms/1
may have severe impact
on performance if there is a large number of registered names or
keys.
info(NameOrPid::Process) -> [{Tag, Info}] | undefined
Like process_info(PidOfProcess)
, but with added
proc-related attributes.
This function calls process_info(PidOfProcess)
, and adds to the
result the following info items:
{pid, pid()}
-- the pid of the process{names, Names}
-- all unique proc names
registered by the process{properties, Props}
-- all non-unique propertiesinfo(NameOrPid::Process, Attr) -> {Attr, Info}
Like process_info(PidOfProcess, Attr)
but accepts some
additional attributes.
All attributes supported by erlang:process_info/2
are
supported by this function. In addition, the following attributes are
handled:
pid
-- the pid of the process (mainly here for symmetry)names
-- all unique names registered in proc by Process
properties
-- all non-unique properties of Process
is_counter(Property) -> true | false
Check whether Property
is a counter property.
Counter properties are created through add_counter/2
, and
behave as normal properties with the following exceptions:
update_counter/2
replace_property/2
is_counter(Pid::Process, Property) -> true | false
Check whether Propery
registered under Process
is a counter
property.
Process
can be either a pid or a registered name.
is_property(Property) -> true | false
Returns true
if Property
is a published property of the current
process.
is_property(Pid::Process, Property) -> true | false
Check whether Property is in fact a property registered with Process.
Process
can be either a pid or a registered name.
last(Type::names | properties) -> Key | '$end_of_table'
Analogous to ets:last/1
.
The tables corresponding to names
and properties
both have
ordered_set
semantics.
next(Type::names | properties, Prev::Key) -> Key | '$end_of_table'
Analogous to ets:next/2
.
The tables corresponding to names
and properties
both have
ordered_set
semantics. The key format of the properties
table is
{Property, Pid}
, while the key format of the names
table is
simply the name. Note that names
and properties
are not likely
the physical names of the actual tables.
pids(Property) -> [pid()]
Returns all pids for which a property Property
is published.
To be more precise, Property
can be any pattern that would be
accepted by //stdlib/ets:select/2
, e.g. '_'
If one imagines an ordered_set ets
table Tab
where all properties
are stored on the form {{Property,Pid},1}
, then calling
this function is equivalent to calling
ets:select(Tab, [{{{Property,'$1'},'_'}, [], ['$1']}]).
Note that this is also true as regards performance. If the Key
pattern is unbound, the operation will be a linear search.
pids(Property, Guards::list()) -> [pid()]
Similar to pids/1
, but also allowing select guards.
If one imagines an ordered_set ets
table Tab
where all non-unique
keys are stored on the form {{Property,Pid},1}
, then calling
this function is equivalent to calling
ets:select(Tab, [{{{Property,'$1'},'_'}, Guards, ['$1']}]).
Note that this is also true as regards performance. If the Property
pattern is unbound, the operation will be a linear search.
previous(Type::names | properties, Next::Key) -> Key | '$end_of_table'
Analogous to ets:previous/2
.
The tables corresponding to names
and properties
both have
ordered_set
semantics. The key format of the properties
table is
{Property, Pid}
, while the key format of the names
table is
simply the name. Note that names
and properties
are not likely
the physical names of the actual tables.
properties_by_pid(P::pid()) -> [Property]
Lists all properties for a given process.
properties_by_pid(P::pid(), KeyPat) -> [Property]
Lists all properties for a given process that match the pattern KeyPat.
Equivalend to properties_by_pid(P, KeyPat, [])
.
properties_by_pid(P::pid(), KeyPat, Guards) -> [Property]
Like properties_by_pid/2
, but with an added list of guards.
The Guards list may be one returned from the function guards/1
.
read_counter(Name) -> integer()
Read the value of a counter property for the current process.
read_counter(Pid::Process, Name) -> integer()
Read the value of a counter property published by Process
.
reg(Pid::Name) -> true
Register a unique Name
. Returns true
or exits.
This function differs from erlang:register(Name,Pid)
in
the following ways:
replace_property(OldProp::OldProperty, NewProperty) -> true
Equivalent to del_property(OldProperty), add_property(NewProperty), but much more efficient.
If OldProperty
is not a published property of the current process
(see add_property/1
), the function exits with badarg
.
One could use properties as a "published process dictionary",
e.g. by replacing put(Tag,Value)
with
proc:add_property({Tag,Value})
, and get(Tag)
with (roughly)
proc:properties_by_pid(self(),Tag)
.
While this would be somewhat less efficient than the built-in process
dictionary, it has the advantage of allowing other processes to key
on process meta-data in a much more efficient and disciplined way than
{_,Dict} = process_info(Pid,dictionary), lists:keysearch(Tag,1,Dict)
(Which makes no distinction between public and private data, and therefore
is rightfully frowned upon, and hopefully never attempted.)"
Note: This function does not work on counter properties.
replace_property(Process, OldProperty, NewProperty) -> true
Replace OldProperty
with NewProperty
on behalf of Process
.
This function is allowed only if permission to replace properties
has been given through Process
calling grant_access/2
.
If permission to replace properties has not been given, this function
exits with access
.
select(Continuation) -> {[Obj], NewContinuation} | '$end_of_table'
Analogous to ets:select/1
.
This function is intended to be called with a Continuation
returned from select_names/1
or select_properties/2
.
select_fold_properties(Fun, Acc, Patterns) -> NewAcc
Like fold_properties/3
but more flexible as it allows
for combining several patterns into one query.
Patterns
is composed as for select_properties/1
.
select_fold_properties(Fun, Acc, Patterns, Limit) -> NewAcc
Like select_fold_properties/3
, but works in batches of Limit
objects at a time, in order to improve raw performance.
select_fold_properties/3
uses a default limit of 1 object at a
time.
This function is equivalent to
select_fold_properties(Fun,Acc,Patterns,Limit,fun(_) -> true end)
,
(see select_fold_properties/5
.)
select_fold_properties(Fun::function(), Acc, Patterns::Property, Limit::integer(), Regulator::function()) -> NewAcc
Like select_fold_properties/4
, but applies a
"Regulator function"
after each batch of objects before proceeding with the next one.
The Regulator
function is expected to take the current accumulator
as an argument and return either true
(in which case processing
continues), or false
(in which case the select_fold_properties/5
function breaks and returns the current accumulator.
select_names(Patterns) -> {Objs, Continuation} | '$end_of_table'
Returns {Name,Pid}
objects one at a time based on
a given selection of all registered unique names.
Patterns
can be written as follows:
* Patterns = [MatchFunction] | '_' * MatchFunction = {MatchHead, [Guard], [Result]} * MatchHead = "Pattern as in ets:match" * Guard = {"Guardtest name", ...} * Result = true (if object is to be included)
or generated using select_pattern/1
or
select_pattern/2
.
The function is almost equivalent to
ets:select(Tab,Patterns, 100)
on an ordered_set
table Tab
with the following representation:
{{Key, Value}, Pid}
The difference compared to ets:select/3
is the Result
expression.
In this function, Result
is expected to be 'true' for those
objects that are to be included.
For convenience, the special pattern '_' is accepted,
and expanded to [{'_', [], [true]}]
.
Any other patterns are ignored.
The Continuation
returned can be used when calling select/1
in order to continue processing.
select_names(Patterns0::Patterns, Limit) -> {Objs, Continuation} | '$end_of_table'
Like select_names/1
, but works in batches of Limit
objects at a time, in order to improve raw performance.
select_pattern(What) -> Patterns
Helper function to generate select patterns from the more
intuitive patterns Property
(or Name
, as it works equally for names).
The return value from this function can be used in e.g.
select_properties/1
, select_properties/2
,
select_fold_properties/3
,
select_fold_properties/4
or select_fold_properties/5
,
or similarly, select_names/1
, select_names/2
,
select_fold_names/3
, select_fold_names/4
, or
select_fold_names/5
.
Patterns
is a list of match specifications on the same form as
that used by //stdlib/ets:select_delete/2
and
//stdlib/ets:select_count/2
,
that is:
* Patterns = [MatchFunction] | '_' * MatchFunction = {MatchHead, [Guard], [Result]} * MatchHead = "Pattern as in ets:match" * Guard = {"Guardtest name", ...} * Result = true (if object is to be included)
select_pattern(What, Guards) -> Patterns
As select_pattern/1
, but with the option to add Guard
expressions.
select_properties(Patterns) -> {Objs, Continuation} | '$end_of_table'
Returns {Property,Pid}
objects one at a time based on
a given selection of all registered instances of Key
.
Patterns
can be written as follows:
* Patterns = [MatchFunction] | '_' * MatchFunction = {MatchHead, [Guard], [Result]} * MatchHead = "Pattern as in ets:match" * Guard = {"Guardtest name", ...} * Result = true (if object is to be included)
or generated using select_pattern/1
or
select_pattern/2
.
For convenience, the special pattern '_' is also accepted.
It expands to [{'_', [], [true]}]
.
The Continuation
returned can be used when calling select/1
in order to continue processing.
select_properties(Patterns0::Patterns, Limit::integer()) -> {Objs, Continuation} | '$end_of_table'
Like select_properties/1
but works in batches of Limit
objects at a time in order to improve raw performance.
send(Pid::Name, Msg) -> Msg
Analogous to Name ! Msg
, except that send({Node,Dest}, Msg)
will be interpreted as 'send to the local process registered as
{Node, Dest}'. If Name is a pid, this function will send the message
to the process with process identifier Name (recall that it is not
possible to register a pid as a unique name in proc.)
set_access(Access::[{Action, Processes, Ops}]) -> true
Control the ability of Processes to perform certain functions on behalf of the current process.
Op
must be one of
add_property
replace_property
del_property
properties
(perform all operations on properties)add_counter
update_counter
del_counter
counters
(perform all operations on counters)Processes
is a list of registered names and/or pids.
Example:
set_access([{grant, ["foo","bar"], [update_counter]}, {revoke, ["baz"], [properties]}])
Allows the processes registered as "foo"
and "bar"
to update
counters, and makes sure that "baz"
is no longer able to add, delete
or replace properties.
start_link() -> {ok, pid()}
Starts the proc server.
proc
assumes that the proc_tabs
module is available, and that
the proc_tabs
process is running.
unreg(Name) -> true
Unregister Name
This function exits if Name
isn't registered to the current
process.
update_counter(Name, Incr) -> integer()
Update the counter attribute of a counter property.
This function only works on counter properties. The Incr
argument
is passed as-is to //stlib/ets:update_counter/3
.
If a complex option, such as {Pos, Incr}
is used,
Pos
must be equal to 2.
update_counter(Process, Name, Value::Incr) -> integer()
Update counter attribute on behalf of Process
.
This function is allowed only if permission to update counters
has been given through Process
calling grant_access/2
.
If permission to update counters has not been given, this function
exits with access
.
where(Name) -> pid() | undefined
Analogous to erlang:whereis(Name)