Использование ets: foldl как forEach для бедных на каждой записи - PullRequest
5 голосов
/ 05 декабря 2010

Короткая версия: безопасно ли использовать ets:foldl для удаления каждой записи ETS, когда вы их просматриваете?

Предположим, что таблица ETS накапливает информацию, и теперь пришло времяобработайте все это.Запись читается из таблицы, используется каким-то образом, а затем удаляется.(Также предположим, что таблица private, поэтому проблем с параллелизмом нет.)

На другом языке с аналогичной структурой данных вы можете использовать цикл for ... each, обрабатывая каждую запись и затем удаляяэто из хеша / dict / map / что угодно.Однако модуль 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.Так как я, по сути, вытираю таблицу, хочу быть уверенным.

Я использую Erlang R14B с таблицей set, однако я хотел бы знать, есть ли какие-либо предостережения с любой версией Erlang,любой тип стола.Спасибо!

Ответы [ 2 ]

8 голосов
/ 05 декабря 2010

Ваш подход безопасен.Причина, по которой это безопасно, заключается в том, что ets:foldl/3 для внутреннего использования ets:first/1, ets:next/2 и ets:safe_fixtable/2.У них есть гарантия, которую вы хотите, а именно, что вы можете убивать элементы и при этом получить полный ход.См. CONCURRENCY раздел erl -man ets.

. Для удаления всех элементов из таблицы существует более простой однострочный:это не работает, если вы хотите выполнить IO-форматирование для каждой строки, в этом случае ваш подход с foldl, вероятно, проще.

1 голос
/ 06 декабря 2010

В таких случаях мы будем чередовать две таблицы или просто создавать новую таблицу каждый раз, когда начинаем обработку. Когда мы хотим начать цикл обработки, мы переключаем авторов на использование альтернативной или новой таблицы, затем выполняем обработку и очищаем или удаляем старую таблицу.

Мы делаем это, потому что в противном случае могут быть одновременные обновления кортежа, которые мы могли бы пропустить. Когда мы используем эту технику, мы работаем с высокочастотными параллельными счетчиками.

...