2010-12-05 3 views
5

짧은 버전 : ets:foldl을 사용하여 모든 ETS 레코드를 삭제하는 것이 안전합니까?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 documentation은 데이터 구조를 수정하는 과정에서 일반적인 우려가 있지만 foldl 내부의 레코드를 수정하는 것이 ETS에 매우 편합니다. 본질적으로 테이블을 깨끗이 닦고 있기 때문에 확실하게 알고 싶습니다.

내가 Erlang R14B를 set 테이블과 함께 사용하고 있지만, Erlang 버전이나 모든 유형의 테이블에주의 사항이 있는지 알고 싶습니다. 감사!

답변

8

접근 방법은 안전합니다. 그 이유는 내부적으로 ets:foldl/3이 과 ets:safe_fixtable/2을 사용하기 때문입니다. 이것들은 여러분이 원하는 것을 보장합니다. 즉, 여러분은 요소를 죽일 수 있고 여전히 전체 트래버스를 얻을 수 있습니다. 동시 처리 섹션의 erl -man ets을 참조하십시오. 테이블에서 모든 요소를 ​​당신의 제거를위한

그러나 간단한 한 줄이 :

ets:match_delete(ex, '_'). 

것은 당신이 각각의 행에 대해 IO-서식하고 싶지해야 작동하지 않지만 어떤에서 케이스가 foldl 인 경우가 더 쉽습니다.

+0

감사합니다. 매뉴얼 페이지의 * Concurrency * 섹션은 필자가 놓친 것입니다. 'safe_fixtable'을 사용하면 모든 객체가 한번 방문됩니다. 그리고 네, 제 실제 코드에서는 데이터를 "처리 완료"라고 표시하기 전에 데이터에 대해 복잡한 처리를하고 있습니다 : 삭제. 건배! – JasonSmith

1

이와 같은 경우 처리를 시작할 때마다 두 개의 테이블을 번갈아 사용하거나 새 테이블을 만듭니다. 처리주기를 시작하려면 작성자가 대체 또는 새 테이블을 사용하도록 전환 한 다음 처리를 수행하고 이전 테이블을 지우거나 삭제하십시오.

우리가 놓칠 수도있는 튜플에 대한 동시 업데이트가있을 수 있기 때문에이 작업을 수행합니다. 우리는이 기술을 사용할 때 고주파 동시 카운터로 작업하고 있습니다.

+0

코드 재로드 메커니즘과 매우 비슷하기 때문에 멋지다. forelab로 foldl을 사용하는 것에 대한 나의 초기 관심사가 이제 해결되었으므로 카운터를 올바르게 유지하는 방법을 기억하는 것이 좋습니다 (이는 내가하는 일이기도합니다). 감사! – JasonSmith

관련 문제