3

您能否通过“最佳实践”方法帮助我,只迭代 ETS 表中的所有元素一次,同时更新每个元素?我的表是一个私有集,我正要遍历它ets:foldlets:update_element在我的输入函数中使用,但我不确定这是否是一种安全的方法,因为破坏性地更新元素可能会再次给我相同的元素 -根据文档。我不打算插入新键,只更新值,请告诉我,这种方法是否安全,或者告诉我另一种有效实现更新的方法!

谢谢!

4

2 回答 2

1

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

我认为ets文档已经回答了您的担忧:

ETS 中没有其他支持可以保证对象之间的一致性。但是,safe_fixtable/2 函数可用于保证一系列 first/1 和 next/2 调用将无错误地遍历表,并且即使另一个进程(或相同的过程)同时删除或插入对象到表中。没有更多的保证;特别是在这种遍历期间插入或删除的对象可能会被访问​​一次或根本不访问。内部遍历表的函数,如 select 和 match,将提供与 safe_fixtable 相同的保证。

于 2014-10-12T00:51:06.650 回答
1

这是我最终得到的,也许有人会觉得它有用:

%% @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 ) ).
于 2014-10-12T14:14:24.837 回答