5

简短版本:在ets:foldl迭代每个 ETS 记录时删除它们是否安全?

假设 ETS 表正在积累信息,现在是时候处理所有信息了。从表中读取一条记录,以某种方式使用,然后删除。(另外,假设表是private,所以没有并发问题。)

在另一种语言中,具有类似的数据结构,您可以使用 for...each 循环,处理每条记录,然后将其从 hash/dict/map/whatever 中删除。但是,该ets模块没有foreach例如lists

但这可能有效:

1> ets:new(ex, [named_table]).
ex
2> ets:insert(ex, {alice, "high"}).
true
3> ets:insert(ex, {bob, "medium"}).
true
4> ets:insert(ex, {charlie, "low"}).
true
5> ets:foldl(fun({Name, Adjective}, DontCare) ->
      io:format("~p has a ~p opinion of you~n", [Name, Adjective]),
      ets:delete(ex, Name),
      DontCare
   end, notused, ex).
bob has a "medium" opinion of you
alice has a "high" opinion of you
charlie has a "low" opinion of you
notused
6> ets:info(ex).
[...
 {size,0},
 ...]
7> ets:lookup(ex, bob).
[]

这是首选方法吗?它至少是正确且没有错误的吗?

我对在处理数据结构时修改数据结构有一个普遍的担忧,但是ets:foldl 文档暗示 ETS 对您修改内部记录非常满意foldl。因为我基本上是在把桌子擦干净,所以我想确定一下。

我正在使用带有set表格的 Erlang R14B,但是我想知道任何 Erlang 版本或任何类型的表格是否有任何警告。谢谢!

4

2 回答 2

8

你的方法是安全的。安全的原因是ets:foldl/3内部使用ets:first/1, ets:next/2ets:safe_fixtable/2. 这些具有您想要的保证,即您可以杀死元素并仍然获得完整的遍历。请参阅 的并发部分erl -man ets

为了从表中删除所有元素,有一个更简单的单行但是:

ets:match_delete(ex, '_').

尽管如果您想为每一行进行 IO 格式化,它不起作用,在这种情况下,您的方法foldl可能更容易。

于 2010-12-05T19:42:41.577 回答
2

对于这种情况,我们将在两个表之间交替,或者每次开始处理时只创建一个新表。当我们想要开始一个处理周期时,我们切换编写器以开始使用备用表或新表,然后我们进行处理并清除或删除旧表。

我们这样做是因为我们可能会错过对元组的并发更新。当我们使用这种技术时,我们正在使用高频并发计数器。

于 2010-12-06T03:32:31.813 回答