<div dir="ltr"><div class="gmail_default" style="font-family:arial,helvetica,sans-serif">In a bag you can have multiple tuples with the same key. So you would store</div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif"><br></div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif">{123, jane}</div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif">{123, john}</div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif">{123, bob}</div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif">{456, joe}</div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif">{456, alice}</div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif"><br></div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif">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.</div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif"><br></div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif">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.</div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif"><br></div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Thu, Apr 22, 2021 at 2:08 PM Frank Muller <<a href="mailto:frank.muller.erl@gmail.com">frank.muller.erl@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="auto">Can’t see how the bag type can help with concurrent update Jesper. </div><div dir="auto"><br></div><div dir="auto">I still need a read, update followed by a write.</div><div dir="auto">Am I wrong?</div><div><br><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div class="gmail_default" style="font-family:arial,helvetica,sans-serif"><br>Another path is to figure out if the ETS type 'bag' is more suitable in your situation.</div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Thu, Apr 22, 2021 at 1:46 PM Sverker Eriksson <<a href="mailto:sverker.eriksson@ericsson.com" target="_blank">sverker.eriksson@ericsson.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div lang="SV"><div><p class="MsoNormal"><span lang="EN-US" style="color:rgb(26,26,26)">It seems </span><span lang="EN-US" style="font-family:"Calibri Light",sans-serif;color:rgb(26,26,26)">ets:select_replace</span><span lang="EN-US" style="color:rgb(26,26,26)"> could be your solution.<u></u><u></u></span></p><p class="MsoNormal"><span lang="EN-US" style="color:rgb(26,26,26)"><u></u> <u></u></span></p><p class="MsoNormal"><span lang="EN-US" style="color:rgb(26,26,26)">The documentation contains this example usage to do a compare-and-swap for a single key:<u></u><u></u></span></p><p class="MsoNormal"><span lang="EN-US" style="font-size:10pt;font-family:Courier;color:rgb(26,26,26)"><u style="font-family:Courier"></u> <u style="font-family:Courier"></u></span></p><p class="MsoNormal"><span lang="EN-US" style="font-size:10pt;font-family:Courier;color:rgb(26,26,26)">[Old] = ets:lookup(T, Key),<u style="font-family:Courier"></u><u style="font-family:Courier"></u></span></p><p class="MsoNormal"><span lang="EN-US" style="font-size:10pt;font-family:Courier;color:rgb(26,26,26)">New = update_object(Old),<u style="font-family:Courier"></u><u style="font-family:Courier"></u></span></p><p class="MsoNormal"><span lang="EN-US" style="font-size:10pt;font-family:Courier;color:rgb(26,26,26)">Success = (1 =:= ets:select_replace(T, [{Old, [], [{const, New}]}])),<u style="font-family:Courier"></u><u style="font-family:Courier"></u></span></p><p class="MsoNormal"><span lang="EN-US" style="font-size:10pt"><u></u> <u></u></span></p><p class="MsoNormal"><span lang="EN-US">/Sverker<u></u><u></u></span></p><p class="MsoNormal"><span lang="EN-US"><u></u> <u></u></span></p><div style="border-style:solid none none;border-top-width:1pt;padding:3pt 0cm 0cm;border-top-color:rgb(225,225,225)"><p class="MsoNormal" style="margin-left:65.2pt"><b><span lang="EN-US">From:</span></b><span lang="EN-US"> erlang-questions <<a href="mailto:erlang-questions-bounces@erlang.org" target="_blank">erlang-questions-bounces@erlang.org</a>> <b>On Behalf Of </b>Frank Muller<br><b>Sent:</b> den 22 april 2021 13:32<br><b>To:</b> Erlang-Questions Questions <<a href="mailto:erlang-questions@erlang.org" target="_blank">erlang-questions@erlang.org</a>><br><b>Subject:</b> ETS: update list value without race condition<u></u><u></u></span></p></div><p class="MsoNormal" style="margin-left:65.2pt"><u></u> <u></u></p><div><p class="MsoNormal" style="margin-left:65.2pt"><span style="border:1pt none windowtext;padding:0cm;color:rgb(49,49,49)">Hi guys</span><u></u><u></u></p><div style="border:1pt none rgb(49,49,49);padding:0cm;word-spacing:1px"><p class="MsoNormal" style="margin-left:65.2pt"><span style="color:rgb(49,49,49)"><u></u> <u></u></span></p></div><div style="border:1pt none rgb(49,49,49);padding:0cm;font-size:1rem;word-spacing:1px"><p class="MsoNormal" style="margin-left:65.2pt"><span style="color:rgb(49,49,49)">I’ve a little issue I’m unable to solve with the current ETS API.<u></u><u></u></span></p></div><div style="border:1pt none rgb(49,49,49);padding:0cm;font-size:1rem;word-spacing:1px"><p class="MsoNormal" style="margin-left:65.2pt"><span style="color:rgb(49,49,49)"><u></u> <u></u></span></p></div><div style="border:1pt none rgb(49,49,49);padding:0cm;font-size:1rem;word-spacing:1px"><p class="MsoNormal" style="margin-left:65.2pt"><span style="color:rgb(49,49,49)">My table is of type set. Keys are integers and values are list of names:<u></u><u></u></span></p></div><div style="border:1pt none rgb(49,49,49);padding:0cm;font-size:1rem;word-spacing:1px"><p class="MsoNormal" style="margin-left:65.2pt"><span style="color:rgb(49,49,49)">123 -> [ jane, john, bob ]<u></u><u></u></span></p></div><div style="border:1pt none rgb(49,49,49);padding:0cm;word-spacing:1px"><p class="MsoNormal" style="margin-left:65.2pt"><span style="border:1pt none windowtext;padding:0cm;color:black">456 -> [ joe, alice ]</span><span style="color:rgb(49,49,49)"><u></u><u></u></span></p></div><div style="border:1pt none rgb(49,49,49);padding:0cm;word-spacing:1px"><p class="MsoNormal" style="margin-left:65.2pt"><span style="border:1pt none windowtext;padding:0cm;color:black">…</span><span style="color:rgb(49,49,49)"><u></u><u></u></span></p></div><div style="border:1pt none rgb(49,49,49);padding:0cm;word-spacing:1px"><p class="MsoNormal" style="margin-left:65.2pt"><span style="color:rgb(49,49,49)"><u></u> <u></u></span></p></div><div style="border:1pt none rgb(49,49,49);padding:0cm;word-spacing:1px"><p class="MsoNormal" style="margin-left:65.2pt"><span style="border:1pt none windowtext;padding:0cm;color:black">Process A with Key=123 wants to delete ‘Jane’ while process B with Key=123 wants to add ‘Adam’.</span><span style="color:rgb(49,49,49)"><u></u><u></u></span></p></div><div style="border:1pt none rgb(49,49,49);padding:0cm;word-spacing:1px"><p class="MsoNormal" style="margin-left:65.2pt"><span style="color:rgb(49,49,49)"><u></u> <u></u></span></p></div><div style="border:1pt none rgb(49,49,49);padding:0cm;word-spacing:1px"><p class="MsoNormal" style="margin-left:65.2pt"><span style="border:1pt none windowtext;padding:0cm;color:black">First, they both needs to read the value associated with Key=123, update that list accordingly and set back the new value.</span><span style="color:rgb(49,49,49)"><u></u><u></u></span></p></div><div style="border:1pt none rgb(49,49,49);padding:0cm;word-spacing:1px"><p class="MsoNormal" style="margin-left:65.2pt"><span style="color:rgb(49,49,49)"><u></u> <u></u></span></p></div><div style="border:1pt none rgb(49,49,49);padding:0cm;word-spacing:1px"><p class="MsoNormal" style="margin-left:65.2pt"><span style="border:1pt none windowtext;padding:0cm;color:black">But this lead to race condition (ex. process B could put back ‘jane’ - last write wins).</span><span style="color:rgb(49,49,49)"><u></u><u></u></span></p></div><div style="border:1pt none rgb(49,49,49);padding:0cm;word-spacing:1px"><p class="MsoNormal" style="margin-left:65.2pt"><span style="color:rgb(49,49,49)"><u></u> <u></u></span></p></div><div style="border:1pt none rgb(49,49,49);padding:0cm;word-spacing:1px"><p class="MsoNormal" style="margin-left:65.2pt"><span style="border:1pt none windowtext;padding:0cm;color:black">Could this problem be solved atomically without involving explicit locking per Key?</span><span style="color:rgb(49,49,49)"><u></u><u></u></span></p></div><div style="border:1pt none rgb(49,49,49);padding:0cm;word-spacing:1px"><p class="MsoNormal" style="margin-left:65.2pt"><span style="color:rgb(49,49,49)"><u></u> <u></u></span></p></div><div style="border:1pt none rgb(49,49,49);padding:0cm;word-spacing:1px"><p class="MsoNormal" style="margin-left:65.2pt"><span style="border:1pt none windowtext;padding:0cm;color:black">Is there any other better way to represent this data set which will not suffer from the race condition?</span><span style="color:rgb(49,49,49)"><u></u><u></u></span></p></div></div><div><div style="border:1pt none rgb(49,49,49);padding:0cm;word-spacing:1px"><p class="MsoNormal" style="margin-left:65.2pt"><span style="color:rgb(49,49,49)"><u></u> <u></u></span></p></div><div style="border:1pt none rgb(49,49,49);padding:0cm;word-spacing:1px"><p class="MsoNormal" style="margin-left:65.2pt"><span style="color:rgb(49,49,49)">Thanks<u></u><u></u></span></p></div><div style="border:1pt none rgb(49,49,49);padding:0cm;font-size:1rem;word-spacing:1px"><p class="MsoNormal" style="margin-left:65.2pt"><span style="color:rgb(49,49,49)">/Frank<u></u><u></u></span></p></div></div></div></div></blockquote></div><br clear="all"><div><br></div>-- <br><div dir="ltr">J.</div>
</blockquote></div></div>
</blockquote></div><br clear="all"><div><br></div>-- <br><div dir="ltr" class="gmail_signature">J.</div>