Erlang ets:foldl与已删除元素

Erlang ets:foldl与已删除元素,erlang,ets,Erlang,Ets,报告说: 如果函数将对象插入表中,或另一个进程将对象插入表中,则这些对象可能会(取决于键顺序)被包括在遍历中 但是如果Function从表中删除对象会发生什么情况?在这种情况下,是否可以保证所有剩余的对象都将包含在遍历中?根据ets.erl的来源,如果一个进程正在迭代表,并且在此期间删除了记录,那么这些记录将不会被处理,如果它们到目前为止还没有处理 foldl(F, Accu, T) -> ets:safe_fixtable(T, true), First = ets:first(

报告说:

如果
函数
将对象插入表中,或另一个进程将对象插入表中,则这些对象可能会(取决于键顺序)被包括在遍历中


但是如果
Function
从表中删除对象会发生什么情况?在这种情况下,是否可以保证所有剩余的对象都将包含在遍历中?

根据ets.erl的来源,如果一个进程正在迭代表,并且在此期间删除了记录,那么这些记录将不会被处理,如果它们到目前为止还没有处理

foldl(F, Accu, T) ->
  ets:safe_fixtable(T, true),
  First = ets:first(T),
  try
    do_foldl(F, Accu, First, T)
  after
    ets:safe_fixtable(T, false)
  end.
辅助函数是

do_foldl(F, Accu0, Key, T) ->
  case Key of
    '$end_of_table' ->
      Accu0;
    _ ->
      do_foldl(F,
               lists:foldl(F, Accu0, ets:lookup(T, Key)),
               ets:next(T, Key), T)
  end.
首先,foldl修复了表。当一个进程修复一个表时,它将被记录到一个{Time,Pid}列表中。在固定表中,ets:first和ets:next保证成功,每个对象只返回一次。对于有序表,ets:next可以返回对象不再存在的键。但这不是一个问题,因为ets:lookup会在记录不在表中的情况下返回一个空列表。列表:foldl在这种情况下不会失败

所以答案是肯定的,其他记录将由ets:foldl处理

如果有多个进程同时操作表,safe_fixtable将保护表不受并发操作的影响。safe_fixtable/2的文件说明:

进程通过调用safe_fixtable(Tab,true)来修复表。该表保持固定,直到进程通过调用safe_fixtable(Tab,false)释放它,或者直到进程终止

注意此处的文档说明:

请注意,在释放固定表之前,不会从固定表中删除任何已删除的对象。如果进程修复了一个表,但从未释放它,那么被删除对象使用的内存将永远不会被释放。表上操作的性能也将显著降低

因此,为遍历修复表是有代价的。不要在foldl函数中执行太多操作,也不应该花费太长时间