遍历和更新Erlang ETS表中的所有元素是最好的方法



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

谢谢!

您可以使用first/1next/2。请参阅此处的next/2文档:http://www.erlang.org/doc/man/ets.html#next-2

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

ETS内没有其他可保证对象之间的一致性。但是,safe_fixtable/2函数可以用于保证第一个/1和下一个/2调用的序列遍历表时没有错误,并且表只访问一次,即使另一个进程(或相同的进程)进程)同时将对象删除或插入到表中。没有什么可以保证的了;特别是插入或在这样的遍历期间被删除的可以被访问一次或者根本不被访问。内部遍历表的函数,如select和match,将提供与safe_fixtable相同的保证。

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

%% @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 ) ).

相关内容

  • 没有找到相关文章

最新更新