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テーブルでErlangR14Bを使用していますが、Erlangバージョン、またはテーブルのタイプにも注意点があるかどうかを知りたいです。ありがとう!

4

2 に答える 2

8

あなたのアプローチは安全です。安全である理由は、内部ets:foldl/3で使用することです。これらはあなたが望む保証を持っています、すなわちあなたが要素を殺し、それでも完全なトラバースを得ることができるということです。のCONCURRENCYセクションを参照してください。ets:first/1, ets:next/2ets:safe_fixtable/2erl -man ets

ただし、テーブルからすべての要素を削除するために、より単純なワンライナーがあります。

ets:match_delete(ex, '_').

各行に対してIOフォーマットを実行したい場合は機能しませんが、その場合は、を使用したアプローチのfoldl方がおそらく簡単です。

于 2010-12-05T19:42:41.577 に答える
2

このような場合、処理を開始するたびに2つのテーブルを交互に使用するか、新しいテーブルを作成します。処理サイクルを開始する場合は、ライターを切り替えて代替テーブルまたは新しいテーブルの使用を開始し、処理を実行して古いテーブルをクリアまたは削除します。

これを行うのは、そうでなければ、見逃す可能性のあるタプルへの同時更新が発生する可能性があるためです。この手法を使用する場合は、高周波同時カウンターを使用しています。

于 2010-12-06T03:32:31.813 に答える