概要:
内置的存储
描述:
这个模块是Erlang内置存储BIFs的接口。这些提供了在Erlang运行时系统中存储大量数据的能力,而且可以对数据进行持续的访问时间。(在ordered_set的状况下,参见下面,访问时间与存储的对象数量的对数成正比。)
数据被组织成一组动态表,能够存储元组。每一个表都是由一个进程建立的。当进程终止时,表将被自动销毁。每一个表在建立时都具备访问权限。
表分为四种不一样的类型:set、ordered_set、bag和duplicate_bag。set或ordered_set表只能有一个与每一个键相关联的对象。bag或duplicate_bag能够有许多与每一个键相关联的对象。
在一个Erlang节点存储的表的数量是有限的。当前的缺省限制大约是1400个表。在启动Erlang运行时系统以前,能够经过设置环境变量 ERL_MAX_ETS_TABLES 来增长上限(例如,使用-env选项到erl/werl)。实际的限制可能比指定的要稍微高一些,但永远不会下降。
注意,表中没有自动垃圾收集。即便没有任何进程的引用,也不会自动销毁,除非全部者进程终止。它能够经过 delete/1 显式地销毁。默认的全部者是建立表的过程。表全部权能够经过使用继承人选项或显式地调用 give_away/3 来转移。
一些实现细节:
在当前的实现中,每个对象插入和查找操做都会产生一个对象的副本;
'$end_of_table' 不该该用做键,由于在使用first/next时,这个原子被用来标记表的末尾。
一样值得注意的是匹配和比较相等之间的细微差异,这是由不一样的表类型 set 和 ordered_set 所演示的。两个Erlang项匹配,若是它们是相同类型且具备相同的值,那么1匹配1,而不是1.0(1.0是浮点数而不是整数)。两个Erlang的项比较相等,要么它们是相同类型和值的,要么二者都是数值类型并扩展到相同的值,那么1比1和1.0都是同样的。ordered_set在Erlang项顺序上工做,在整数和浮点之间没有定义的顺序,它扩展到相同的值,所以键1和键1.0在ordered_set表中被认为是相等的。node
故障:
通常来讲,若是任何参数的格式是错误的,那么下面的函数将会退出,若是表标识符是无效的,或者因为表访问权限而拒绝操做(protected or private)。
并发:
这个模块为并发访问提供了一些有限的支持。对单个对象的全部更新都保证是原子性的和隔离性的。这意味着对单个对象的更新操做要么成功,要么彻底失败,彻底没有任何影响(原子性)。其余进程(隔离性)也不能看到更新的中间结果。一些更新了几个对象的函数代表,它们甚至能够保证整个操做的原子性和隔离性。在数据库术语中,隔离级别能够被看做是“可序列化的”,就好像全部的隔离操做都是串行地执行的,一个接一个地以严格的顺序执行。
匹配规范:
有些函数使用匹配规范,match_spec。在select/2中给出了一个简短的解释。有关详细描述,请参阅ERTS用户指南中的“Erlang中的匹配规范”一章。
数据类型:
access() = public | protected | private
continuation()
select/1,3, select_reverse/1,3, match/1,3, and match_object/1,3 使用不透明的 continuation。
match_spec() = [{match_pattern(), [term()], [term()]}]
匹配规范,见上文。
comp_match_spec()
一个编译的匹配规范。
match_pattern() = atom() | tuple()
tab() = atom() | tid()
tid()
一个表标识符,new/2 返回的。
type() = set | ordered_set | bag | duplicate_bag
导出:
all() -> [Tab]
Types:
Tab = tab()
返回节点上全部表的列表。命名表由它们的名称给出,未命名的表由它们的表标识符给出。
delete(Tab) -> true
Types:
Tab = tab()
删除整个表 Tab。
delete(Tab, Key) -> true
Types:
Tab = tab()
Key = term()
从表 Tab中删除全部带有键 Key的对象。
delete_all_objects(Tab) -> true
Types:
Tab = tab()
删除ETS表 Tab中的全部对象。这个操做被保证是原子性的和隔离性的。
delete_object(Tab, Object) -> true
Types:
Tab = tab()
Object = tuple()
从ETS表中删除确切的对象Object,留下具备相同键的对象,但其余不一样(对于类型 bag有用)。在duplicate_bag中,对象的全部实例都将被删除。
file2tab(Filename) -> {ok, Tab} | {error, Reason}
Types:
Filename = file:name()
Tab = tab()
Reason = term()
读取tab2file/2或tab2file/3生成的文件,并建立相应的表 Tab。
至关于 file2tab(Filename,[])。
file2tab(Filename, Options) -> {ok, Tab} | {error, Reason}
Types:
Filename = file:name()
Tab = tab()
Options = [Option]
Option = {verify, boolean()}
Reason = term()
读取tab2file/2或tab2file/3生成的文件,并建立相应的表 Tab。
目前惟一受支持的选项是 {verify,boolean()}。若是验证被打开(经过指定 {verify,true}),该函数将利用文件中存在的任何信息来断言信息没有被破坏。这是如何完成的,取决于使用 tab2file/3编写的 extended_info。
若是文件中没有 extended_info,而且 {verify,true} 是指定的,当转储开始时,所编写的对象的数量将与原始表的大小进行比较。若是表是 public,而且在表被转储到文件时,则会使验证失败。为了不这种类型的问题,要么在同步更新时不验证转储文件,要么使用 {extended_info, [object_count]} 选项到 tab2file/3,它将文件中的信息扩展到实际编写的对象的数量。
若是验证被打开,而且该文件是用 {extended_info, [md5sum]} 编写的,那么读取文件的速度会更慢,消耗的CPU时间也会大大增长。shell
first(Tab) -> Key | '$end_of_table'
Types:
Tab = tab()
Key = term()
返回表 Tab中的第一个键 Key。若是该表是 ordered_set类型,那么Erlang项顺序中的第一个键将被返回。若是表是任何其余类型的,那么根据该表的内部顺序将返回第一个键。若是表是空的,则返回 '$end_of_table'。
使用 next/2在表格中找到后续的键。
foldl(Function, Acc0, Tab) -> Acc1
Types:
Function = fun((Element :: term(), AccIn) -> AccOut)
Tab = tab()
Acc0 = Acc1 = AccIn = AccOut = term()
若是表是空的,则返回Acc0。这个函数相似于 lists:foldl/3。除了类型ordered_set的表以外,表中元素的顺序是不肯定的,它们从头至尾被遍历。
若是函数将对象插入到表中,或者另外一个进程将对象插入到表中,那么这些对象可能(取决于键顺序)包含在遍历中。
foldr(Function, Acc0, Tab) -> Acc1
Types:
Function = fun((Element :: term(), AccIn) -> AccOut)
Tab = tab()
Acc0 = Acc1 = AccIn = AccOut = term()
若是表是空的,则返回Acc0。这个函数相似于 lists:foldr/3。表中元素的顺序是不肯定的,除了类型ordered_set的表以外,它们从尾到头被遍历。
若是函数将对象插入到表中,或者另外一个进程将对象插入到表中,那么这些对象可能(取决于键顺序)包含在遍历中。
from_dets(Tab, DetsTab) -> true
Types:
Tab = tab()
DetsTab = dets:tab_name()
在已经打开的Dets表中,填满已经建立的ETS表,这个表名为DetsTab。除非覆盖,不然ETS表的现有对象将被保留。
若是任何表不存在或dets表不打开,就会抛出一个badarg错误。
fun2ms(LiteralFun) -> MatchSpec
Types:
LiteralFun = function()
MatchSpec = match_spec()
伪函数经过 parse_transform的方式将 LiteralFun翻译成参数,做为参数转换成match_spec在函数调用中。“literal”是指,在文本中,须要将其做为函数的参数来写,它不能被保存在一个变量中,而这个变量又被传递给函数。
解析转换是在模块 ms_transform中实现的,源代码必须包含文件ms_transform.hrl。在STDLIB中为这个伪函数工做。若是不能在源代码中包含hrl文件,将致使运行时错误,而不是编译时的错误。include文件最容易包括添加行-include(“stdlib/include/ms transform.hrl”).到源代码。
fun是很是有限的,它只能接受一个单一的参数(匹配的对象):一个惟一的变量或一个元组。它须要使用is_ 关卡测试。在match_spec中不能使用语言结构(例如,if,case,receive等)是不容许的。
返回值是产生的match_spec。
例子:
1> ets:fun2ms(fun({M,N}) when N > 3 -> M end).
[{{'$1','$2'},[{'>','$2',3}],['$1']}]
来自环境的变量能够被导入,所以它能够工做:
2> X=3.
3
3> ets:fun2ms(fun({M,N}) when N > X -> M end).
[{{'$1','$2'},[{'>','$2',{const,3}}],['$1
导入的变量将被 match_spec 常量表达式替换,这与Erlang funs的静态做用域一致。然而,本地或全局的函数调用不能处于fun的关卡或主体中。固然,对构建match_spec函数的内建调用是容许的:
4> ets:fun2ms(fun({M,N}) when N > X, is_atomm(M) -> M end).
Error: fun containing local Erlang function calls
('is_atomm' called in guard) cannot be translated into match_spec
{error,transform_error}
5> ets:fun2ms(fun({M,N}) when N > X, is_atom(M) -> M end).
[{{'$1','$2'},[{'>','$2',{const,3}},{is_atom,'$1'}],['$1']}]
从这个例子中能够看出,这个函数也能够从 shell中调用。当从shell中使用时,fun也须要在调用中。在shell案例中使用的其余方法是使用parse_transform,但或多或少是相同的限制(例外是记录,由于它们不是由shell处理的)。
警告:
若是 parse_transform没有被应用到调用这个伪函数的模块中,那么调用将在运行时失败(带有badarg)。模块ets实际上导出了一个带有这个名称的函数,可是除了在shell中使用函数时,它永远不该该被调用。若是经过包含 ms_transform.hrl 来正确地应用parse_transform,编译后的代码永远不会调用这个函数,可是函数调用被一个文字匹配规范所取代。
要了解更多信息,请参见mstransform(3)。
give_away(Tab, Pid, GiftData) -> true
Types:
Tab = tab()
Pid = pid()
GiftData = term()
使进程Pid成为表 Tab的新全部者。若是成功,将消息{“ETS-TRANSFER”,Tab,FromPid,GiftData}发送给新全部者。
进程Pid必须是活的,本地的,而不是表的全部者。调用过程必须是表全部者。
请注意,give_away 并不会影响到表的继承人选项。例如,表全部者能够将继承人设置为本身,将表放在一边,而后将其取回,以防接收方终止。
i() -> ok
在tty显示全部ETS表的信息。
i(Tab) -> ok
Types:
Tab = tab()
在tty上浏览表Tab。
info(Tab) -> InfoList | undefined
Types:
Tab = tab()
InfoList = [InfoTuple]
InfoTuple = {compressed, boolean()}
| {heir, pid() | none}
| {keypos, integer() >= 1}
| {memory, integer() >= 0}
| {name, atom()}
| {named_table, boolean()}
| {node, node()}
| {owner, pid()}
| {protection, access()}
| {size, integer() >= 0}
| {type, type()}
将表 Tab的信息返回为元组列表。若是Tab有正确的表标识符类型,但不引用现有的ETS表,则返回未定义。若是Tab不是正确的类型,那么这个函数就会由于badarg而失败。
{compressed, boolean()}
表示表是否被压缩。
{heir, pid() | none}
表的继承者的pid,若是没有继承者,则为none。
{keypos, integer() >= 1}
键位置。
{memory, integer() >= 0
分配给表的空间(以字为单位)。
{name, atom()}
表名。
{named_table, boolean()}
代表表是否被命名。
{node, node()}
存放表的节点。这个字段再也不有意义,由于表不能从其余节点访问。
{owner, pid()}
表全部者的pid。
{protection, access()}
表访问的权限。
{size, integer() >= 0
在表中插入的对象的数量。
{type, type()}
表的类型。
info(Tab, Item) -> Value | undefined
Types:
Tab = tab()
Item = compressed
| fixed
| heir
| keypos
| memory
| name
| named_table
| node
| owner
| protection
| safe_fixed
| size
| stats
| type
Value = term()
返回表的相关信息,若是Tab不引用现有的ETS表,则返回未定义的信息。若是Tab不是正确的类型,或者若是Item不是容许的值之一,那么这个函数就会由于badarg而失败。
警告:
在R11B和更早的时候,这个函数不会失败,可是对于条目的无效值返回undefined。
对info/1,除了{Item,Value}定义,下面的项也被容许:
Item=fixed, Value=boolean()
表示表是否由任何进程固定。
Item=safe_fixed, Value={FirstFixed,Info}|false 若是表是使用safe_fixtable/2修复的,那么调用返回一个元组,其中FirstFixed是表第一次被进程修复的时间,它多是如今修复的进程之一。Info是一个可能的空列表,它是一个元组{Pid,RefCount},一个元组,每一个进程如今都是固定的。RefCount是参考计数器的值,它记录了进程中表被修复了多少次。
若是表从未被修复,则调用返回false。
Item=stats, Value=tuple()
返回关于OTP测试套件使用的内部格式的set、bag和duplicate_bag表的内部统计信息。不适合生产使用。
init_table(Tab, InitFun) -> true
Types:
Tab = tab()
InitFun = fun((Arg) -> Res)
Arg = read | close
Res = end_of_input | {Objects :: [term()], InitFun} | term()
用调用输入函数InitFun建立的对象来替换表Tab的现有对象,以下所示。这个函数是为了与dets模块兼容而提供的,它并不比使用ets:insert/2来填充表效率更高。
当被调用时,读取函数InitFun被假定为返回end_of_input,当没有更多的输入,或{Objects,Fun},Objects是一个对象列表,而fun是一个新的输入函数。任何其余值的值都做为错误,返回{error,{init_fun,Value}}。每个输入函数都将被调用一次,若是出现错误,最后一个函数会在参数关闭时被调用,它的应答将被忽略。
若是表的类型被设定,而且有多个对象和一个给定的键,那么就会选择其中一个对象。这并不必定是在输入函数返回的对象序列中给定键的最后一个对象。这也适用于存储在类型bag表中的重复对象。
insert(Tab, ObjectOrObjects) -> true
Types:
Tab = tab()
ObjectOrObjects = tuple() | [tuple()]
将列表ObjectOrObjects中的对象或全部对象插入到表Tab中。若是表是一个set,而且插入的对象的键与表中任何对象的键相匹配,那么旧对象将被替换。若是表是一个ordered_set,而且插入的对象的键与表中的任何对象的键相等,那么旧对象也会被替换。若是列表中包含了不止一个带有匹配键的对象,而且该表是一个set,那么就会插入一个对象,其中一个没有定义。对于ordered_set也是同样的,可是若是键比较相等,也会发生一样的事情。
整个操做被保证是原子性的和隔离性的,即便插入了一个对象列表。
insert_new(Tab, ObjectOrObjects) -> boolean()
Types:
Tab = tab()
ObjectOrObjects = tuple() | [tuple()]
这个函数的工做原理与insert/2彻底相同,除了用相同的键重写对象(在set或ordered_set的状况下),或者在表中已经存在的键中添加更多的对象(在bag和duplicate_bag的状况下),它只是返回false。若是ObjectOrObjects是一个列表,那么这个函数在插入任何东西以前都会检查每一个键。若是列表中没有列出全部的键,则不会插入任何东西。与insert/2同样,整个操做都保证是原子性的和隔离性的。
is_compiled_ms(Term) -> boolean()
Types:
Term = term()
这个函数用来检查一个术语是不是有效编译的match_spec。编译的match_spec是一种不透明的数据类型,不能在Erlang节点之间发送,也不能存储在磁盘上。任何试图建立一个编译的match_spec的外部表示的尝试都会致使一个空的二进制(<<>>)。下面的表达式,做为一个例子:
ets:is_compiled_ms(ets:match_spec_compile([{'_',[],[true]}])).
会产生true:
MS = ets:match_spec_compile([{'_',[],[true]}]),
Broken = binary_to_term(term_to_binary(MS)),
ets:is_compiled_ms(Broken).
会产生错误,由于变量被破坏将包含一个通过编译的match_spec,它已经经过外部表示。
请注意:
编译匹配规范没有外部表示的事实是出于性能考虑。它可能会在未来的版本中发生变化,而这个接口仍然会保持向后兼容的缘由。
last(Tab) -> Key | '$end_of_table'
Types:
Tab = tab()
Key = term()
根据ordered_set类型的表Tab返回最后一个键Key。若是表是任何其余类型的,那么该函数就是first/2的同义词。若是表为空,则返回“$end_of_table”。
使用prev/2来查找表中的前键。
lookup(Tab, Key) -> [Object]
Types:
Tab = tab()
Key = term()
Object = tuple()
在表Tab中返回全部带有键key的对象列表。
在set、bag和duplicate_bag的状况下,只有当给定的键与表中对象的键相匹配时,才会返回一个对象。然而,若是表示一个ordered_set,那么若是给定的键比表中的对象的键相等,则返回一个对象。区别和=:=和==同样。做为一个例子,你能够在ordered_set中插入一个带有integer() 1的对象,并将该对象做为lookup/2的键,得到查找的结果;和用float() 1.0 做为key查找。
若是表是类型set或ordered_set,则函数返回空列表或带有一个元素的列表,由于不能有多个具备相同键的对象。若是表是类型bag或duplicate_bag,则该函数返回任意长度的列表。
注意对象插入的时间顺序被保留;用给定的键插入的第一个对象将首先出如今结果列表中,以此类推。
在表中插入和查找时间,set、bag和duplicate_bag是常量,无论表的大小。对于ordered_set的数据类型,时间与对象数量的对数成比例。
lookup_element(Tab, Key, Pos) -> Elem
Types:
Tab = tab()
Key = term()
Pos = integer() >= 1
Elem = term() | [term()]
若是表Tab是类型set或ordered_set,则该函数返回带有键key的位置为Pos的元素。
若是表是bag或duplicate_bag,那么函数将返回一个列表,其中包含每一个对象的Pos位置的元素。
若是没有键Key的对象,则该函数将以理由badarg退出。
一方面,set、bag和duplicate_bag之间的区别,另外一方面是ordered_set,关于ordered_set的认为键在比较相等时是相等的,而其它表类型只在匹配时才相等,lookup_element和lookup天然适用。
match(Tab, Pattern) -> [Match]
Types:
Tab = tab()
Pattern = match_pattern()
Match = [term()]
将表Tab中的对象与模式Pattern匹配。
模式是一个项,可能包含:
绑定部分(Erlang项),
它与任何Erlang项相匹配,
模式变量:$N,N=0,1,……
该函数为每个匹配对象返回一个含有其中元素的列表,其中每一个元素都是模式变量绑定的有序列表。一个例子:
6> ets:match(T, '$1'). % Matches every object in the table
[[{rufsen,dog,7}],[{brunte,horse,5}],[{ludde,dog,5}]]
7> ets:match(T, {'_',dog,'$1'}).
[[7],[5]]
8> ets:match(T, {'_',cow,'$1'}).
[]
若是在模式中指定了键,那么匹配是很是有效的。若是没有指定键,也就是说,若是它是一个变量或一个下划线,那么必须搜索整个表。若是表很是大,搜索时间可能会很大。
在ordered_set类型的表中,结果与first/next遍历的顺序是相同的。
match(Tab, Pattern, Limit) -> {[Match], Continuation} | '$end_of_table'
Types:
Tab = tab()
Pattern = match_pattern()
Limit = integer() >= 1
Match = [term()]
Continuation = continuation()
跟 ets:match/2 同样,都是根据匹配模式 Pattern 匹配表 Tab 里的对象数据,可是 ets:match/3 只返回 Limit 条的匹配数据。返回结果里还同时返回变量 Continuation,这可做为下一次调用 ets:match/1 方法的参数来获取下一批的匹配数据,这比使用 ets:first/1 和 ets:next/2 方法遍历获取表里的对象数据会更快,更有效率。
若是表是空的,则返回$end_of_table。
match(Continuation) -> {[Match], Continuation} | '$end_of_table'
Types:
Match = [term()]
Continuation = continuation()
继续从 ets:match/3 方法开始匹配数据,调用 ets:match/3 方法跟匹配数据一块儿返回的变量 Continuation 可用在下一次调用这个函数来获取下一批的匹配数据。
当表中没有更多的对象时,“$end_of_table”就会返回。
match_delete(Tab, Pattern) -> true
Types:
Tab = tab()
Pattern = match_pattern()
从表Tab中删除与模式Pattern匹配的全部对象。有关模式的描述,请参阅match/2。
match_object(Tab, Pattern) -> [Object]
Types:
Tab = tab()
Pattern = match_pattern()
Object = tuple()
将表Tab中的对象与模式Pattern匹配。有关模式的描述,请参阅match/2。该函数返回与模式匹配的全部对象的列表。
若是在模式中指定了键,那么匹配是很是有效的。若是没有指定键,也就是说,若是它是一个变量或一个下划线,那么必须搜索整个表。若是表很是大,搜索时间可能会很大。
在ordered_set类型的表格中,结果与first/next遍历的顺序是相同的。
match_object(Tab, Pattern, Limit) -> {[Match], Continuation} | '$end_of_table'
Types:
Tab = tab()
Pattern = match_pattern()
Limit = integer() >= 1
Match = [term()]
Continuation = continuation()
跟 ets:match_object/2 同样,都是根据匹配模式 Pattern 匹配表 Tab 里的对象数据,可是 ets:match_object/3 只返回 Limit 条的匹配数据。返回结果里还同时返回变量 Continuation,这可做为下一次调用 ets:match_object/1 方法的参数来获取下一批的匹配数据,这比使用 ets:first/1 和 ets:next/2 方法遍历获取表里的对象数据更快,更有效率。
若是表是空的,则返回$end_of_table。
match_object(Continuation) -> {[Match], Continuation} | '$end_of_table'
Types:
Match = [term()]
Continuation = continuation()
继续从 ets:match_object/3 方法开始匹配数据,调用 ets:match_object/3 方法跟匹配数据一块儿返回的变量 Continuation 可用在下一次调用这个函数来获取下一批的匹配数据。
当表中没有更多的对象时,“$end_of_table”就会返回。
match_spec_compile(MatchSpec) -> CompiledMatchSpec
Types:
MatchSpec = match_spec()
CompiledMatchSpec = comp_match_spec()
这个函数把一个匹配规范 MatchSpec 转换为一个可用于被 ets:match_spec_run/2 在后续调用的内部表示形式。转换后的内部形式"不透明"的一个数据,它并不能转回为其原来的外部数据格式,而且无缺无损的转回(这意味着它不能够发送到另外一节点的进程上,而且仍然是一个有效的已编译的匹配规范,或存储在磁盘上也是不行)。
若是“MatchSpec”这个项不能被编译(不表明有效的MatchSpec),就会抛出一个badarg错误。
注意:
这个函数在普通代码中使用有限,dets使用它来执行dets:select操做。
match_spec_run(List, CompiledMatchSpec) -> list()
Types:
List = [tuple()]
CompiledMatchSpec = comp_match_spec()
这个函数是用一个已编译的匹配规范对一个元组形式的列表进行指定匹配,参数 CompiledMatchSpec 是函数 ets:match_spec_compile/1 调用产生的匹配规范,所以是该函数想用的匹配规范的内部表示形式。
该匹配操做会对列表里的每个元素进行匹配操做,并返回一个包含全部结果的列表。若是列表里的一个元素并不符合匹配,将不会返回任何数据。所以返回的结果列表的长度有可能会小于参数列表的长度。
下面的两个调用将给出相同的结果(但确定不是相同的执行时间。)
Table = ets:new...
MatchSpec = ....
% The following call...
ets:match_spec_run(ets:tab2list(Table),
ets:match_spec_compile(MatchSpec)),
% ...will give the same result as the more common (and more efficient)
ets:select(Table,MatchSpec),
注意:
这个函数在普通代码中使用有限,它被dets用来执行dets:select操做和Mnesia事务中。
member(Tab, Key) -> boolean()
Types:
Tab = tab()
Key = term()
像lookup/2同样工做,但不返回对象。若是表格中的一个或多个元素有键Key,则返回true;反之则返回false。
new(Name, Options) -> tid() | atom()
Types:
Name = atom()
Options = [Option]
Option = Type
| Access
| named_table
| {keypos, Pos}
| {heir, Pid :: pid(), HeirData}
| {heir, none}
| Tweaks
Type = type()
Access = access()
Tweaks = {write_concurrency, boolean()}| {read_concurrency, boolean()}| compressed
Pos = integer() >= 1
HeirData = term()
建立一个新的表并返回一个表标识符,它能够在后续操做中使用。表格标识符能够被发送到其余进程,以便在一个节点内的不一样进程之间共享一张表。
参数选项是一个原子列表,它指定表类型、访问权限、键位置,以及表是否被命名。若是遗漏了一个或多个选项,则使用默认值。这意味着不指定任何选项与指定[set, protected, {keypos,1}, {heir,none}, {write_concurrency,false}, {read_concurrency,false}]相同。
set
设置表是一个set表——一个键,一个对象,对象之间没有顺序。这是默认的表类型。
ordered_set
表是一个orderedset表——一个键,一个对象,在Erlang项顺序中排序,这是由<and>操做符所暗示的顺序。这种类型的表在某些状况下的行为与其余类型的表有所不一样。最明显的是,ordered_set表在比较相等时,将键视为相等,而不只仅是匹配时。这意味着对于ordered_set来讲,integer()1和float()1.0被认为是相等的。这也意味着用于查找元素的键不必定与返回的元素中的键相匹配,若是float()和integer()的键混合在表的键中。
bag
这个表是一个bag表,它能够有不少对象,可是每一个对象只有一个实例,每一个键。
duplicate_bag
这个表是一个duplicate_bag表,它能够有许多对象,包括同一对象的多个副本,每一个键。
public
任何进程均可以读或写到表中。
protected
全部者进程能够读取和写入表。其余进程只能读取表。这是存取权的默认设置。
private
只有全部者进程能够读写表。
named_table
若是这个选项存在,名称Name与表标识符相关联。而后,能够在后续操做中使用名称代替表标识符。
{keypos,Pos}
在存储的元组中,应该使用哪一个元素做为键。默认状况下,它是第一个元素,即Pos=1。然而,这并不老是合适的。特别地,咱们不但愿第一个元素成为键,若是咱们想把Erlang记录存储在一张表中。
注意,表中存储的任何元组必须至少有Pos数量的元素。
{heir,Pid,HeirData} | {heir,none}
设定一个进程做为继承者。若是全部者终止,继承者将继承该表。当这种状况发生时,将会把消息{'ETS-TRANSFER',tid(),FromPid,HeirData} 发送给继承者。继承者必须是一个本地进程。默认的继承者是none,当全部者终止时,它将破坏表。
{write_concurrency,boolean()}
性能调优。默认为false,在这种状况下,一个对表进行改变(写入)的操做将得到独占访问,阻塞同一表的任何并发访问,直到完成为止。若是设置为true,该表针对并发写访问进行了优化。同一表的不一样对象能够经过并发进程进行改变(和读取)。这在必定程度上是以牺牲内存消耗和顺序访问和并发读取的性能为代价的。write_concurrency选项能够与write_concurrency选项相结合。一般,当大型并发读爆发和大型并发写爆发是常见的(请参阅write_concurrency选项的文档以得到更多信息),您一般但愿将它们组合在一块儿。注意,这个选项不会改变任何关于原子性和隔离性的保证。在多个对象(如insert/2)中作出这样的承诺的函数将从这个选项中得到更少(或没有)。
在当前的实现中,表类型ordered_set不受此选项的影响。此外,write并发性和read并发性所形成的内存消耗是每一个表的一个常量开销。当两个选项组合在一块儿时,这个开销可能会特别大。
{read_concurrency,boolean()}
性能调优。默认是false。当设置为true时,该表针对并发读操做进行了优化。当在带有SMP支持的运行时系统上启用此选项时,读取操做将变得更加便宜;特别是在有多个物理处理器的系统上。然而,在读写操做之间切换变得更加昂贵。当并发读操做比写操做要频繁得多,或者当并发读和写出现大的读和写时,您一般但愿启用这个选项。不少读操做都不会被写,不少的写操做都不会被读中断。当常见的访问模式是一些读操做,并重复使用一些写操做时,您一般不但愿启用这个选项。在这种状况下,启用这个选项得到性能降低。read_concurrency选项能够与write_concurrency选项相结合。一般,当大型并发读爆发和大型并发写爆发是常见的时候,您一般须要将它们组合在一块儿。
compressed
若是存在这个选项,那么表数据将以更紧凑的格式存储,以减小内存。缺点是它会使表操做变慢。特别是须要检查整个对象的操做,例如match和select,将会变得更慢。在当前的实现中,关键元素没有被压缩。
next(Tab, Key1) -> Key2 | '$end_of_table'
Types:
Tab = tab()
Key1 = Key2 = term()
返回下一个键Key2,按照表Tab中的键Key1。若是该表是ordered_set类型,那么Erlang项顺序中下一个键就会返回。若是表是任何其余类型的表,那么根据表的内部顺序返回下一个键。若是没有下一个键,就会返回“$end_of_table”。
使用first/1来找到表格中的第一个键。
除非使用safe_fixtable/2来保护一组类型set、bag或duplicate_bag的表,不然,若是对表进行并发更新,则遍历可能会失败。若是该表是ordered_set的,那么函数就会按顺序返回下一个键,即便对象已经不存在了。
prev(Tab, Key1) -> Key2 | '$end_of_table'
Types:
Tab = tab()
Key1 = Key2 = term()
按照ordered_set类型的表Tab中的Erlang项顺序返回前面的键Key2。若是表是任何其余类型的,那么该函数就是next/2的同义词。若是没有之前的键,则返回“$end_of_table”。
使用last/1来找到表中的最后一个键。
rename(Tab, Name) -> Name
Types:
Tab = tab()
Name = atom()
将命名的表Tab从新命名为新名称。以后,旧的名称不能用于访问表。重命名一个未命名的表没有效果。
repair_continuation(Continuation, MatchSpec) -> Continuation
Types:
Continuation = continuation()
MatchSpec = match_spec()
这个函数能够用来恢复ets:select/3或ets:select/1的不透明延续,若是延续已经经过了外部项格式(在节点之间发送或存储在磁盘上)。
这个函数的缘由是延续项包含了编译的match_spec,所以若是转换为外部项格式,将会失效。考虑到原始的match_spec是完整的,延续能够被恢复,这意味着它能够再次被用于后续的ets:select/1调用,即便它已经存储在磁盘上或另外一个节点上。
做为一个例子,如下的调用序列将失败:
T=ets:new(x,[]),
...
{_,C} = ets:select(T,ets:fun2ms(fun({N,_}=A)
when (N rem 10) =:= 0 -> A end),10),
Broken = binary_to_term(term_to_binary(C)),
ets:select(Broken).
…下面的顺序将会起做用:
T=ets:new(x,[]),
...
MS = ets:fun2ms(fun({N,_}=A)
when (N rem 10) =:= 0 -> A end),
{_,C} = ets:select(T,MS,10),
Broken = binary_to_term(term_to_binary(C)),
ets:select(ets:repair_continuation(Broken,MS)).
…正如对ets:repair_continuation/2的调用将从新创建(谨慎地)失效的延续。
注意:
在应用程序代码中不多须要这个函数。它被Mnesia用于实现分布式select/3和select/1序列。一个普通的应用程序要么使用Mnesia,要么保持延续不被转换为外部格式。
没有一个编译的matchspec的外部表示的缘由是性能。它可能会在未来的版本中发生变化,而这个接口将保留向后兼容性。
safe_fixtable(Tab, Fix) -> true
Types:
Tab = tab()
Fix = boolean()
锁定一个类型是 set,bag 或 duplicate_bag 的表,使其能够安全遍历表里的数据。
一个进程经过调用safe_fixtable(Tab, true)来锁定一个表。该表保持不变,直到进程经过调用safe_fixtable(Tab, false)释放它,或者直到进程终止为止。
若是同时有几个进程锁定一个表,那么表会一直保持锁定状态,直到全部进程都释放它(或崩溃)。有一个引用计数器记录着每一个进程的操做,有 N 个持续的锁定操做必须有 N 个释放操做,表才会真正被释放。
当一个表被锁定,一序列的ets:first/1和ets:next/2的调用都会保证成功执行,而且表里的每个对象数据只返回一次,即便在遍历的过程当中,对象数据被删除或插入。在遍历过程当中插入到表里的新数据可能由 ets:next/2 返回(这取决有键的内部顺序)。
clean_all_with_value(Tab,X) ->
safe_fixtable(Tab,true),
clean_all_with_value(Tab,X,ets:first(Tab)),
safe_fixtable(Tab,false).数据库
clean_all_with_value(Tab,X,'$end_of_table') ->
true;
clean_all_with_value(Tab,X,Key) ->
case ets:lookup(Tab,Key) of
[{Key,X}] ->
ets:delete(Tab,Key);
_ ->
true
end,
clean_all_with_value(Tab,X,ets:next(Tab,Key)).
一个被锁定的表是不会有被删除的对象数据从表里被实际删除,直到它被释放。若是一个进程锁定一个表,并不释放它,那些已删除的对象数据所占用的内存将永远不会获得释放。对表操做的性能也会显著下降。
可使用 ets:info/2 来查看有哪些进程锁定了表。有不少进程锁定表的系统须要一个监控来给那些锁定表很长时间的进程发送警告消息。
对于 ordered_set 类型的表,ets:safe_fixtable/2 是不必的,由于 ets:first/1 和 ets:next/2 将总会调用成功。
select(Tab, MatchSpec) -> [Match]
Types:
Tab = tab()
MatchSpec = match_spec()
Match = term()
使用一个匹配描述从表 Tab 里匹配对象。此函数调用比 ets:match/2 和 ets:match_object/2 更经常使用。如下是一些最简单形式的匹配描述:
MatchSpec = [MatchFunction]
MatchFunction = {MatchHead, [Guard], [Result]}
MatchHead = "Pattern as in ets:match"
Guard = {"Guardtest name", ...}
Result = "Term construct"
这意味着匹配描述老是含有一个以上元组元素的列表(含有三个参数的元组元素),元组的第一个元素应是 ets:match/2 的文档中所描述的模式,第二个元素应是含 0 个或多个断言测试的列表,第三个元素应是包含关于实际返回值的描述的列表,一般是一个对返回值全描述的列表,即返回匹配对象的全部项目。
返回值的结构使用 MatchHead 所绑定的 "match variables",或者使用特殊的匹配值 '$_'(整个匹配对象)和 '$$'(包含全部匹配值的列表)。安全
ets:match(Tab,{'$1','$2','$3'}) 等同于 ets:select(Tab,[{{'$1','$2','$3'},[],['$$']}])
ets:match_object(Tab,{'$1','$2','$1'}) 等同于 ets:select(Tab,[{{'$1','$2','$1'},[],['$_']}])
复合术语能够经过简单地编写一个列表来构造结果部分,所以下面的代码:
ets:select(Tab,[{{'$1','$2','$3'},[],['$$']}]) 等同于 ets:select(Tab,[{{'$1','$2','$3'},[],[['$1','$2','$3']]}])
在匹配头中全部绑定的变量做为一个列表。若是要构造元组,就必须在元组中编写一个元组,其中的单个元素是tuple想要构造的元组(由于普通的元组可能被误认为是一个守卫)。所以下面的调用:
ets:select(Tab,[{{'$1','$2','$1'},[],['$_']}]) 等同于 ets:select(Tab,[{{'$1','$2','$1'},[],[{{'$1','$2','$3'}}]}])
这种语法至关于跟踪模式中使用的语法(参见see dbg(3))
这些警卫被构形成元组,其中第一个元素是测试的名称,其他的元素是测试的参数。要检查绑定到匹配变量$1的元素的特定类型(好比列表),您能够将测试写成{is_list,'$1'}。若是测试失败,表中的对象将没法匹配,而且将尝试下一个MatchFunction(若是有的话)。可使用Erlang中的大多数警卫测试,可是只有新版本的前缀is_是容许的(如is_float、is_atom等)。
警卫部分还能够包含逻辑和算术运算,它们使用与警卫测试(前缀表示法)相同的语法编写,所以在Erlang中编写的警卫测试是这样的:
is_integer(X), is_integer(Y), X + Y < 4711
像这样表示(X换成'$1'和Y换成'$2'):
[{is_integer, '$1'}, {is_integer, '$2'}, {'<', {'+', '$1', '$2'}, 4711}]
在ordered_set类型的表格中,对象的访问顺序与first/next遍历的顺序相同。这意味着匹配规范将在first/next顺序中对带有键的物体执行,相应的结果列表将按照该执行的顺序执行。
select(Tab, MatchSpec, Limit) -> {[Match], Continuation} | '$end_of_table'
Types:
Tab = tab()
MatchSpec = match_spec()
Limit = integer() >= 1
Match = term()
Continuation = continuation()
用法跟 ets:select/2 类似,但只返回限定数量(Limit)的匹配对象数据。Continuation 项可在后续的 ets:select/1 调用中获取下一组的匹配对象数据。在操做表中对象数据时,这是一种颇有效的操做方式,而且比经过调用 ets:first/1 和 ets:next/1 逐个访问对象还要快。
若是表是空的,则返回$end_of_table。
select(Continuation) -> {[Match], Continuation} | '$end_of_table'
Types:
Match = term()
Continuation = continuation()
继续从 ets:select/3 开始的匹配。 下一次匹配到的限定数量 Limit(Limit 由 ets:select/3 初始所得)的对象数据将与新的 Continuation 一块儿返回,新的 Continuation 将在后续调用该函数时被使用。
若是表中已没有剩余的对象,则返回 '$end_of_table'。
select_count(Tab, MatchSpec) -> NumMatched
Types:
Tab = tab()
MatchSpec = match_spec()
NumMatched = integer() >= 0
使用match_spec将表Tab中的对象与之匹配。若是匹配的对象返回true的话,该对象就会被认为是匹配并被计算在内。对于任何来自match_spec的结果,对象不被认为是匹配的,所以不被计算在内。
这个函数能够被描述为一个matchd_elete/2,它实际上并不删除任何元素,但只计算它们。
这个函数返回匹配的对象的数量。
select_delete(Tab, MatchSpec) -> NumDeleted
Types:
Tab = tab()
MatchSpec = match_spec()
NumDeleted = integer() >= 0
使用一个匹配规范 MatchSpec 来匹配表 Tab 里的对象数据。若是对一条对象数据使用匹配规范时返回 true,而且该条对象数据会从表里移除。对于任何被匹配规范(match_spec)所匹配到的对象数据会被做为返回值而保留下来。该函数比 ets:match_delete/2 还更通用(ets:match_delete/2 的代码实现里还调用到 ets:select_delete/2 方法)。
函数最后会返回一个实际在表里被删除的对象的数量值。
select_reverse(Tab, MatchSpec) -> [Match]
Types:
Tab = tab()
MatchSpec = match_spec()
Match = term()
像select/2这样的工做,可是对于ordered_set表类型返回列表的顺序是相反的。对于全部其余表类型,返回值与select/2的返回值相同。
select_reverse(Tab, MatchSpec, Limit) -> {[Match], Continuation} | '$end_of_table'
Types:
Tab = tab()
MatchSpec = match_spec()
Limit = integer() >= 1
Match = term()
Continuation = continuation()
像select/3这样的工做,可是对于ordered_set表类型,遍历是在Erlang项顺序的最后一个对象上开始的,并向第一个方向移动。对于全部其余表类型,返回值与select/3相同。
请注意,这并不等同于反转select/3调用的结果列表,由于结果列表不只颠倒了,并且还包含了表中最后的Limit匹配对象,而不是第一个。
select_reverse(Continuation) -> {[Match], Continuation} | '$end_of_table'
Types:
Continuation = continuation()
Match = term()
继续从ets:select_reverse/3开始一个匹配。若是是ordered_set类型的表,表的遍历将继续从Erlang数据里最先的键的对象数据开始。返回的列表也将包含跟键按相反的顺序的对象数据。
若是是其余类型的的表,那么该函数的效用跟 ets:select/1 同样。
例子:
1> T = ets:new(x,[ordered_set]).
2> [ ets:insert(T,{N}) || N <- lists:seq(1,10) ].
...
3> {R0,C0} = ets:select_reverse(T,[{'_',[],['$_']}],4).
...
4> R0.
[{10},{9},{8},{7}]
5> {R1,C1} = ets:select_reverse(C0).
...
6> R1.
[{6},{5},{4},{3}]
7> {R2,C2} = ets:select_reverse(C1).
...
8> R2.
[{2},{1}]
9> '$end_of_table' = ets:select_reverse(C2).
...
setopts(Tab, Opts) -> true
Types:
Tab = tab()
Opts = Opt | [Opt]
Opt = {heir, pid(), HeirData} | {heir, none}
HeirData = term()
设置表选项。目前惟一容许在表被建立以后设置的选项是heir。调用过程必须是表全部者。
slot(Tab, I) -> [Object] | '$end_of_table'
Types:
Tab = tab()
I = integer() >= 0
Object = tuple()
这个函数主要用于调试,一般应该使用first/next或last/prev。
返回表Tab的I:th槽中的全部对象。一个表能够经过重复调用该函数来遍历,从第一个槽I=0开始,并在返回“$end_of_table”时结束。若是I参数超出了范围,那么这个函数就会失败。
除非使用safe_fixtable/2来保护类型set、bag或duplicate_bag的表,不然,若是对表进行并发更新,则遍历可能会失败。若是该表是ordered_set的,那么该函数将返回包含Erlang项顺序中的I:th对象的列表。
tab2file(Tab, Filename) -> ok | {error, Reason}
Types:
Tab = tab()
Filename = file:name()
Reason = term()
将表Tab转储到文件Filename。
至关于tab2file(Tab, Filename,[])。
tab2file(Tab, Filename, Options) -> ok | {error, Reason}=
Types:
Tab = tab()
Filename = file:name()
Options = [Option]
Option = {extended_info, [ExtInfo]}
ExtInfo = md5sum | object_count
Reason = term()
将表Tab转储到文件Filename。
当转储表时,关于该表的某些信息会被转储到转储文件开头的头部。这些信息包含关于表类型、名称、保护、大小、版本的数据,若是它是一个命名表。它还包含关于扩展信息被添加到文件中的注释,它能够是文件中对象的计数,也能够是文件头和记录的MD5和。
若是表是public,而且在转储期间从表中添加或删除记录,那么标题中的size字段可能与文件中的实际记录数不一致。在转储期间更新的public表,而且在读取时须要验证,至少须要一个扩展信息的字段,以便之后的读取验证进程是可靠的。
extended_info选项指定将哪些额外信息写入表转储:
object_count
实际上写入文件的对象的数量在文件页脚中被记录,为何即便文件在转储期间被更新,也能够验证文件截断。
md5sum
文件中的头和对象是使用内置的MD5函数来校验的。全部对象的MD5和都写在文件页脚上,这样在读取时验证将检测到文件数据中最轻微的位翻转。使用这种方法须要花费至关多的CPU时间。
当使用extended_info选项时,它会致使在stdlib-1.15.1版本以前的ets版本中没法读取的文件。
tab2list(Tab) -> [Object]
Types:
Tab = tab()
Object = tuple()
返回表Tab中全部对象的列表。
tabfile_info(Filename) -> {ok, TableInfo} | {error, Reason}
Types:
Filename = file:name()
TableInfo = [InfoItem]
InfoItem = {name, atom()}
| {type, Type}
| {protection, Protection}
| {named_table, boolean()}
| {keypos, integer() >= 0}
| {size, integer() >= 0}
| {extended_info, [ExtInfo]}
| {version,
{Major :: integer() >= 0,
Minor :: integer() >= 0}}
ExtInfo = md5sum | object_count
Type = bag | duplicate_bag | ordered_set | set
Protection = private | protected | public
Reason = term()
返回经过tab2file/2或tab2file3导出到文件的表的信息。
如下项目将返回:
name
导出表的名字。若是表是一个命名表,那么当表格使用file2tab/2从文件中加载时,就不可能存在同名的表。若是表没有被保存为指定的表,那么当从文件加载表格时,这个字段根本没有任何意义。
type
ets导出表的类型(即set、bag、duplicate_bag或ordered_set)。这种类型将在再次载入表时使用。
protection
导出表的保护类型(即private, protected 或 public)。从文件中加载的表将获得一样的保护。
named_table
true若是在转储文件时该表是一个命名表,不然false。请注意,当一个具名表从一个文件中加载时,系统中不能存在同名的表。
keypos
将表的keypos转储到文件中,这将在再次加载表格时使用。
size
当表转储到文件时,表中的对象的数量,在公共表的状况下,不须要对应实际保存到文件的对象的数量,由于在表转储期间,对象可能已经被另外一个进程添加或删除了。
extended_info
在文件页脚中写入的扩展信息,容许在表格加载过程当中进行更强的验证,如指定为tab2file/3。注意,这个函数只告诉咱们哪些信息是存在的,而不是文件页脚中的值。该值是一个包含一个或多个原子object_count和md5sum的列表。
version
{Major,Minor}包含了ets表转储文件格式的主要和次要版本。这个版本字段是由stdlib-1.5.1开始添加的,旧版本的文件在这个字段中会返回{0,0}。
若是文件不可访问,严重损坏,或者没有使用tab2file/2或tab2file/3生成的文件,则返回错误。
table(Tab) -> QueryHandle
table(Tab, Options) -> QueryHandle
Types:
Tab = tab()
QueryHandle = qlc:query_handle()
Options = [Option] | Option
Option = {n_objects, NObjects} | {traverse, TraverseMethod}
NObjects = default | integer() >= 1
TraverseMethod = first_next
| last_prev
| select
| {select, MatchSpec :: match_spec()}
返回QLC(Query List Comprehension)查询句柄。模块QLC实现了一种主要针对Mnesia的查询语言,可是ETS表、Dets表和列表也被QLC识别为数据的来源。调用ETS:table/1,2是使ETS表Tab可用到QLC的方法。
当在关键位置上只有简单的限制时,QLC使用ets:lookup/2查找键,但若是不可能,整个表就会被遍历。选项遍历决定了这是如何完成的:
first_next.
表被遍历一次一个键经过调用ets:first/1和ets:next/2。
last_prev.
表被遍历一次一个键经过调用ets:last/1和ets:prev/2。
select.
经过调用ets:select/3和ets:select/1来遍历表。选项n_object决定返回的对象的数量(select/3的第三个参数);默认状况下,一次返回100个对象。match_spec(select/3的第二个参数)由QLC组装:简单的过滤器被转换成等价的匹配规范,而更复杂的过滤器必须应用于select/3返回的全部对象,给定匹配全部对象的match_spec。
{select, MatchSpec}.
至于select表,调用ets:select/3和ets:select/1遍历。不一样之处在于,match_spec是显式的。这就是如何在QLC提供的语法中声明不容易表达的匹配规范。
下面的例子使用一个显式的match_spec来遍历表:
9> true = ets:insert(Tab = ets:new(t, []), [{1,a},{2,b},{3,c},{4,d}]),
MS = ets:fun2ms(fun({X,Y}) when (X > 1) or (X < 5) -> {Y} end),
QH1 = ets:table(Tab, [{traverse, {select, MS}}]).
一个带有隐式match_spec的例子:
10> QH2 = qlc:q([{Y} || {X,Y} <- ets:table(Tab), (X > 1) or (X < 5)]).
后一个例子实际上至关于前者,能够经过函数qlc:info/1来验证。
11> qlc:info(QH1) =:= qlc:info(QH2).
true
qlc:info/1 返回关于查询句柄的信息,在这种状况下,两个查询句柄返回相同的信息。
test_ms(Tuple, MatchSpec) -> {ok, Result} | {error, Errors}
Types:
Tuple = tuple()
MatchSpec = match_spec()
Result = term()
Errors = [{warning | error, string()}]
这个函数是用来测试在调用ets:select/2时使用的match_spec的一个实用程序。这个函数都测试了匹配规范的“语法”正确性,并对对象元组运行Match_Spec。若是匹配规范包含错误,那么元组{error, Errors} 就会返回,Errors是一个天然语言描述的列表,描述了match_spec的错误。若是match_spec在语法上是正确的,那么函数就会返回{ok,Result} ,Result是在真实ets:select/2调用结果:若是匹配规范不匹配对象元组,则返回false。
这是一个有用的调试和测试工具,特别是在编写复杂的ets:select/2调用时。
to_dets(Tab, DetsTab) -> DetsTab
Types:
Tab = tab()
DetsTab = dets:tab_name()
在已经打开的ETS表格中,填满已经建立的/打开的Dets表。在插入对象以前,Dets表被清空。
update_counter(Tab, Key, UpdateOp) -> Result
update_counter(Tab, Key, UpdateOp :: [UpdateOp]) -> [Result]
update_counter(Tab, Key, Incr) -> Result
Types:
Tab = tab()
Key = term()
UpdateOp = {Pos, Incr} | {Pos, Incr, Threshold, SetValue}
Pos = Incr = Threshold = SetValue = Result = integer()
这个函数提供了一种有效的方法来更新一个或多个计数器,而没必要费力地查找一个对象,经过增长一个元素来更新对象,并再次将产生的对象插入到表中。(更新是用原子的方式完成的;也就是说,在操做过程当中,没有进程能够访问ets表。)
它将破坏性地更新表Tab的键Key的对象,增长Incr到Pos:th位置的元素。新的计数器值返回。若是没有指定位置,则会更新下一个键(keypos+1)的元素。
若是指定了阈值,则计数器将被重置为值SetValue,若是下列条件发生:
Incr不是负数(>=0),结果将大于(>)Threshold;
Incr是负的(<0),结果将小于(<)Threshold。
能够提供UpdateOp的列表,以便在对象中执行几个更新操做。操做按照列表中指定的顺序执行。若是相同的计数器位置在列表中不止一次出现,那么相应的计数器将会被更新几回,每次都是基于前面的结果。返回值是每一个更新操做的新计数器值的列表,其顺序与操做列表中的顺序相同。若是指定了空链表,则不会更新任何东西,并返回一个空列表。若是函数失败,则根本不须要更新。
给定的键用来识别对象,经过匹配一个集合表中的对象的键,或者与ordered_set表中的物体的键进行比较(参见lookup/2和new/2,了解差别的详细信息)。
这个函数将会由于badarg而失败,若是:
这个表不是类型set或ordered_set;
没有正确的键存在;
对象的参数是错的;
更新的元素不是整数;
更新的元素也是键,或者任何Pos,Incr,阈值或SetValue都不是整数。
update_element(Tab, Key, ElementSpec :: {Pos, Value}) -> boolean()
update_element(Tab, Key, ElementSpec :: [{Pos, Value}]) -> boolean()
Types:
Tab = tab()
Key = term()
Value = term()
Pos = integer() >= 1
这个函数提供了一种有效的方法来更新对象中的一个或多个元素,而没必要查找、更新和回写整个对象。
该函数把 ETS 表 Tab 里键为 Key 的对象数据的第 Pos 个元素数据的值更改成 Value。
一个{Pos,Value}列表能够更新同一个对象中的几个元素。若是相同的位置在列表中出现不止一个,那么列表中的最后一个值将被写入。若是列表是空的,或者函数失败,则根本不会进行更新。这个函数也是原子的,由于其余进程永远看不到任何中间结果。
若是找到了带有键Key的对象,则该函数返回true;反之则返回false。
给定的键用来识别对象,经过匹配一个set表中的对象的键,或者与ordered_set表中的对象的键进行比较(参见lookup/2和new/2,了解差别的详细信息)。
这个函数将会由于badarg而失败,若是:
这个表不是类型set或ordered_set,
Pos小于1或大于1,或者,
更新的元素也是键。并发