When multiple processes operate on the same ETS table, I usually need to start one or more write processes to perform ETS modifications to ensure data consistency. I guess if I have a function like the one above, I don’t need to start the write process anymore。
It is not technically possible in erts to run Erlang code and hold ETS locks that would guarantee atomicity. It is the same reason why you cannot write an Erlang fun as a match specification.
The functionality you describe could probably be written using some clever use of ets:lookup and ets:select_replace to create a compare and exchange. Something like:
update_with(Table, Key, Fun) ->
[Object] = ets:lookup(Table, Key),
{ok, NewObject} = Fun(Object),
%% Create a match spec that first checks that object is the same, and then replaces it
%% with the new object.
case ets:select_replace(Table, FancyMatchSpec) of
0 -> update_with(Table, Key, Fun);
N -> N
end.
I initially thought that different Fun updates had different FancyMatchSpec matching different field values, because I thought matching the entire OldObject would be performance unfriendly. I’ll test that out later