Domanda

Versione corta: è sicuro da usare ets:foldl eliminare ogni record ETS come uno è l'iterazione attraverso di loro

?

Si supponga che una tabella ETS sta accumulando informazioni e ora è il momento di elaborare il tutto. Un record viene letto dalla tabella, utilizzato in qualche modo, poi cancellato. (Inoltre, assumere la tabella è private, quindi nessun problema di concorrenza.)

In un'altra lingua, con una struttura dati simile, si potrebbe utilizzare un ... per ogni ciclo, l'elaborazione di ogni record e quindi eliminarlo dalla hash / dict / map / qualunque cosa. Tuttavia, il modulo ets non ha foreach come ad esempio lists fa.

Ma questo lavoro potrebbe:

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).
[]

E 'questo l'approccio preferito? E 'di almeno corretto e privo di bug?

Ho una preoccupazione generale sulla modifica di una struttura di dati durante l'elaborazione di esso, tuttavia il ETS: documentazione foldl implica che l'ETS sta abbastanza bene con te modificare i record all'interno foldl. Dal momento che sto essenzialmente pulire il tavolo pulito, voglio essere sicuro.

Sto usando Erlang R14B con un tavolo set però mi piacerebbe sapere se ci sono avvertimenti con qualsiasi versione Erlang, o qualsiasi tipo di tavolo pure. Grazie!

È stato utile?

Soluzione

Il vostro approccio è sicuro. Il motivo è sicuro è che ets:foldl/3 utilizzare internamente ets:first/1, ets:next/2 e ets:safe_fixtable/2. Questi hanno la garanzia che si desidera, e cioè che si può uccidere gli elementi e ancora ottenere il pieno traversata. Vedere la CONCURRENCY di erl -man ets.

Per la vostra rimozione di tutti gli elementi della tabella, v'è un semplice one-liner però:

ets:match_delete(ex, '_').

anche se non funziona si deve voler fare IO-formattazione per ogni riga, nel qual caso il vostro approccio con foldl è probabilmente più facile.

Altri suggerimenti

Per casi come questi ci si alterneranno tra due tabelle o semplicemente creare una nuova tabella ogni volta che si comincia a elaborazione. Quando vogliamo iniziare un ciclo di lavorazione si passa gli scrittori per iniziare a utilizzare il tavolo alternativo o nuovo, allora facciamo la nostra elaborazione e cancellare o eliminare la vecchia tabella.

Lo facciamo perché ci potrebbe essere altrimenti aggiornamenti simultanei di una tupla che potremmo perdere. Stiamo lavorando con i contatori simultanei ad alta frequenza quando usiamo questa tecnica.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top