[erlang-questions] ets:select_delete not atomic?

Oliver Bollmann oliver.bollmann@REDACTED
Mon Aug 12 17:59:41 CEST 2019


Your are right, everything is ok!

A simple example of key pool without gen_servers call, thanks to 
ets:select_delete!!

-module(key_pool). %% API -export([new/1, in/2, in_new/2, out/1, out_compare/1, clear/1]). -spec(new(atom()) -> {ok,atom() | {already_exists,atom()}}). new(Pool)when is_atom(Pool) ->
   case ets:info(Pool,name)of undefined ->
       {ok,ets:new(Pool,
         [ordered_set,named_table,public,
           {write_concurrency,true},{read_concurrency,true}])};
     Pool -> {already_exists,Pool}
   end. -spec(in(atom(),{any(),any()}) -> true). in(Pool,{Key,Val}) ->
   ets:insert(Pool,{Key,Val}). -spec(in_new(atom(),{any(),any()}) -> boolean()). in_new(Pool,{Key,Val}) ->
   ets:insert_new(Pool,{Key,Val}). -spec(out(atom()) -> {ok,{any(),any()} | empty}). out(Pool) ->
   case ets:select(Pool,[{'_',[],['$_']}],1)of {[{Key,_} =Item],_} ->
       case ets:select_delete(Pool,[{{Key,'_'},[],[true]}])of 1 ->
           {ok,Item};
         0 ->
           % context switch receive after 0 -> out(Pool)
           end end;
     '$end_of_table' ->
       empty
   end. -spec(out_compare(atom()) -> {ok,{any(),any()} | empty}). out_compare(Pool) ->
   case ets:select(Pool,[{'_',[],['$_']}],1)of {[{Key,Val} =Item],_} ->
       case ets:select_delete(Pool,[{{Key,Val},[],[true]}])of 1 ->
           {ok,Item};
         0 ->
           % context switch receive after 0 -> out(Pool)
           end end;
     '$end_of_table' ->
       empty
   end. -spec(clear(atom()) -> true). clear(Pool) -> ets:delete_all_objects(Pool). Oliver

On 12.08.19 16:33, Sverker Eriksson wrote:
> On mån, 2019-08-12 at 14:16 +0200, Oliver Bollmann wrote:
>> Hi,
>>
>> EtsName = ets:new(test,[named_table,ordered_set]),
>> Res = ets:select_delete(EtsName,[{{Key},[],[true]}]).
>>
>> Res should be 1 or 0!
>>
>> But if i do this with a lot of process, at the same time,
>> it happend that two process get 1!
>>
>> Start with: ets:insert(EtsName,{Key}).
>>
>> Process One: ets:select_delete(EtsName,[{{Key},[],[true]}]).
>> Process Two: ets:select_delete(EtsName,[{{Key},[],[true]}]).
>>
>> Process One get 1 AND Process Two get 1, with the same key, of course!
>>
>>
>> Is this correct?
>>
> No, that does not seem right.
>
> The table traversals done by ets:select* and ets:match* functions are not
> atomic, but the operation done on each found object should be atomic.
>
> That is, if you do ets:insert(T,{Key}) once and then several
> ets:select_delete(T, [{{Key},[],[true]}]) in parallel, only of of them should
> find {Key} and delete it.
>
> What OTP version is this?
>
> /Sverker
>
> _______________________________________________
> erlang-questions mailing list
> erlang-questions@REDACTED
> http://erlang.org/mailman/listinfo/erlang-questions

-- 
Grüße
Oliver Bollmann

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://erlang.org/pipermail/erlang-questions/attachments/20190812/b6790562/attachment.htm>


More information about the erlang-questions mailing list