遍历和更新Erlang ETS表中所有元素的最佳方法是什么?

时间:2014-10-10 17:10:50

标签: erlang updates traversal ets

你能帮助我采用“最佳实践”方法,只更新一次ETS表中的所有元素,同时更新每个元素吗?我的表是一个私有集,我正在使用ets:foldl在我的输入函数中使用ets:update_element遍历它,但我不确定,如果这是一种安全的方法,那么破坏性地更新元素根据文件,可能会在另一个时间给我相同的元素。我不打算插入新密钥,只更新值,请告诉我,这种方法是否安全,或者向我展示一种有效实现更新的替代方法!

谢谢!

2 个答案:

答案 0 :(得分:1)

您可以使用first/1next/2。在此处查看next/2 doco:http://www.erlang.org/doc/man/ets.html#next-2

我认为ets文档已经回答了您的问题:

  

ETS内没有其他可以保证的支持   对象之间的一致性但是,safe_fixtable / 2函数可以   用于保证第一个/ 1和下一个/ 2个呼叫的序列   遍历表没有错误,并且每个现有对象都在   表只访问一次,即使是另一个进程(或相同的   process)同时删除或插入表中的对象。   没有更多的保证;特别是插入的对象或   在这种遍历期间删除可以被访问一次或根本不访问。   内部遍历表的函数,如select和   匹配,将提供与safe_fixtable相同的保证。

答案 1 :(得分:0)

这是我最终得到的结果,也许有人会发现它很有用:

%% @doc
%% Traverses each element in an ETS table, and calls Fun on them.
%% Use with caution, when inserting or deleting elements, see the
%% ETS documentation for details!
-spec ets_each(
    TableRef :: ets:tid( ),
    Fun      :: fun( ( Key :: term( ), [ Element :: term( ) ], Extra :: term( ) ) -> ok ),
    Extra    :: term( )
) ->
    ok.
ets_each( TableRef, Fun, Extra ) ->
    ets:safe_fixtable( TableRef, true ),
    First = ets:first( TableRef ),
    try
        do_ets_each( TableRef, Fun, Extra, First )
    after
        ets:safe_fixtable( TableRef, false )
    end.

%% @doc
%% Recursive helper function for ets_each.
-spec do_ets_each(
    TableRef :: ets:tid( ),
    Fun      :: fun( ( Key :: term( ), [ Element :: term( ) ], Extra :: term( ) ) -> ok ),
    Extra    :: term( ),
    Key      :: term( )
) ->
    ok.
do_ets_each( _TableRef, _Fun, _Extra, '$end_of_table' ) ->
    ok;    
do_ets_each( TableRef, Fun, Extra, Key ) ->
    Fun( Key, ets:lookup( TableRef, Key ), Extra ),
    do_ets_each( TableRef, Fun, Extra, ets:next( TableRef, Key ) ).