1
votes

from the ets doc, All updates to single objects are guaranteed to be both atomic and isolated. This means that an updating operation to a single object either succeeds or fails completely without any effect (atomicity) and that no intermediate results of the update can be seen by other processes (isolation).

for the following code, I wrapped two tables into one

my questions:

  1. is this a common pattern in Erlang?

  2. for the insert and update, is it atomic and isolated ?

    -module(example_store). -export([init/0, insert/1, update/1]).

    init() -> ets:new(store, [public, named_table, {read_concurrency, true}, {write_concurrency, true}]),

    Data = ets:new(store_data, [public, named_table, {read_concurrency, true}, {write_concurrency, true}]),

    Info = ets:new(store_info, [public,ordered_set,
            named_table,
              {read_concurrency, true},
        {write_concurrency, true}]),
    
     ets:insert(store, {store, Data, Info}).
    
    
    %% insert data
    insert({Key, Value, Info}) ->
       {store, Data_tb, Info_tb} = ets:lookup(store, store),
        ets:insert(Data_tb, {Key, Value}),
        ets:insert(Info_tb, {Info, Key}),
        ok.
    
    
    %% update data
    update({Key, Value, Info, Info_old}) ->
         {store, Data_tb, Info_tb} = ets:lookup(store, store),
         ets:insert(Data_tb, {Key, Value}),
         ets:delete(Info_tb, {Info_old,Key}),
         ets:insert(Info_tb, {Info, Key}),
         ok.   
    

Update_1 from @Derek Brown, the wrapped table cannot guarantee insert/1 and update/1 to be isolated.

Q3 : is that possible to make it isolated? (apart from the Gen_server)

1

1 Answers

1
votes

1) No. The return from ets:new/2 when you use named_table is the same name that you used for the first argument. So that's what you're storing in the store table- the names. So in insert/1 and update/1 you could just as well use the store_data and store_info atoms directly.

2) No, the inserts and updates are neither atomic nor isolated. Not atomic because that's not how functions work in Erlang. If, say, the first ets:insert/2 call in your insert/1 succeeded, but the second failed for some reason, there's not any kind of automatic rollback for the first. And not isolated because there's just no guarantee that a given function (e.g., insert/1 or update/1) will be executed atomically. Other processes could see the intermediate effects before your functions are complete.