ETS: update list value without race condition

Jesper Louis Andersen jesper.louis.andersen@REDACTED
Thu Apr 22 16:08:05 CEST 2021


In a bag you can have multiple tuples with the same key. So you would store

{123, jane}
{123, john}
{123, bob}
{456, joe}
{456, alice}

When you match on e.g., 123, you get back all tuples matching this, so you
can still get the behavior you want and obtain [jane, john, bob]. However,
now, if one process wants to add {123, adam} and another process wants to
delete {123, jane}, it's possible because the rows are different, even if
they have the same key. As your problem is formulated, this works in your
situation. However, I think your problem might be a bit more involved than
this cooked example in reality, so it might not work.

If you have a low number of updates to the table, I usually just make it
protected and then factor all updates through an owning process. Once
there's a single writer things are usually simpler, but beware that you can
still have interleaved reads so one must think about atomicity in this case.


On Thu, Apr 22, 2021 at 2:08 PM Frank Muller <frank.muller.erl@REDACTED>
wrote:

> Can’t see how the bag type can help with concurrent update Jesper.
>
> I still need a read, update followed by a write.
> Am I wrong?
>
>
>> Another path is to figure out if the ETS type 'bag' is more suitable in
>> your situation.
>>
>> On Thu, Apr 22, 2021 at 1:46 PM Sverker Eriksson <
>> sverker.eriksson@REDACTED> wrote:
>>
>>> It seems ets:select_replace could be your solution.
>>>
>>>
>>>
>>> The documentation contains this example usage to do a compare-and-swap
>>> for a single key:
>>>
>>>
>>>
>>> [Old] = ets:lookup(T, Key),
>>>
>>> New = update_object(Old),
>>>
>>> Success = (1 =:= ets:select_replace(T, [{Old, [], [{const, New}]}])),
>>>
>>>
>>>
>>> /Sverker
>>>
>>>
>>>
>>> *From:* erlang-questions <erlang-questions-bounces@REDACTED> *On
>>> Behalf Of *Frank Muller
>>> *Sent:* den 22 april 2021 13:32
>>> *To:* Erlang-Questions Questions <erlang-questions@REDACTED>
>>> *Subject:* ETS: update list value without race condition
>>>
>>>
>>>
>>> Hi guys
>>>
>>>
>>>
>>> I’ve a little issue I’m unable to solve with the current ETS API.
>>>
>>>
>>>
>>> My table is of type set. Keys are integers and values are list of names:
>>>
>>> 123 -> [ jane, john, bob ]
>>>
>>> 456 -> [ joe, alice ]
>>>
>>>>>>
>>>
>>>
>>> Process A with Key=123 wants to delete ‘Jane’ while process B with
>>> Key=123 wants to add ‘Adam’.
>>>
>>>
>>>
>>> First, they both needs to read the value associated with Key=123, update
>>> that list accordingly and set back the new value.
>>>
>>>
>>>
>>> But this lead to race condition (ex. process B could put back ‘jane’ -
>>> last write wins).
>>>
>>>
>>>
>>> Could this problem be solved atomically without involving explicit
>>> locking per Key?
>>>
>>>
>>>
>>> Is there any other better way to represent this data set which will not
>>> suffer from the race condition?
>>>
>>>
>>>
>>> Thanks
>>>
>>> /Frank
>>>
>>
>>
>> --
>> J.
>>
>

-- 
J.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://erlang.org/pipermail/erlang-questions/attachments/20210422/a1611e52/attachment-0001.htm>


More information about the erlang-questions mailing list