From 95dec7497abbdb06defcb23e99fa31e06597496e Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Wed, 3 May 2017 18:22:45 +0200 Subject: erts: Fix ets:select_replace with {const, NewTuple} Enable ets:select_replace to do a generic single object compare-and-swap operation of any ets-tuple using a matchspec like this: [{Old, [], [{const, New}]}] The only exception when this does not work is if the key contains maps or atoms looking like variables (like '$1'). --- lib/stdlib/test/ets_SUITE.erl | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) (limited to 'lib') diff --git a/lib/stdlib/test/ets_SUITE.erl b/lib/stdlib/test/ets_SUITE.erl index 2dfd481665..13a3f99e7e 100644 --- a/lib/stdlib/test/ets_SUITE.erl +++ b/lib/stdlib/test/ets_SUITE.erl @@ -1349,6 +1349,26 @@ t_select_replace(Config) when is_list(Config) -> NeqPairs(X,Y)) || X <- Terms, Y <- Terms], + %% Wrap entire tuple with 'const' + [[begin + Old = {Key, 1, 2}, + ets:insert(T2, Old), + 1 = ets:select_replace(T2, [{Old, [], [{const, New}]}]), + [New] = ets:lookup(T2, Key), + ets:delete(T2, Key) + end || New <- [{Key, 1, 2}, {Key, 3, 4}, {Key, 1}, {Key, 1, 2, 3}, {Key}] + ] + || Key <- [{1, tuple}, {nested, {tuple, {a,b}}} | Terms]], + + %% 'const' wrap does not work with maps or variables in keys + [[begin + Old = {Key, 1, 2}, + {'EXIT',{badarg,_}} = (catch ets:select_replace(T2, [{Old, [], [{const, New}]}])) + end || New <- [{Key, 1, 2}, {Key, 3, 4}, {Key, 1}, {Key, 1, 2, 3}, {Key}] + ] + || Key <- [#{a => 1}, {nested, #{a => 1}}, '$1']], + + ets:delete(T2), verify_etsmem(EtsMem). -- cgit v1.2.3 From 6c3265b86582d4848e1c77efee3a649a137694d6 Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Fri, 5 May 2017 14:51:58 +0200 Subject: stdlib: Add examples for ets:select_replace docs --- lib/stdlib/doc/src/ets.xml | 36 ++++++++++++++++++++++++++++-------- 1 file changed, 28 insertions(+), 8 deletions(-) (limited to 'lib') diff --git a/lib/stdlib/doc/src/ets.xml b/lib/stdlib/doc/src/ets.xml index d1ec176f81..62e97218cd 100644 --- a/lib/stdlib/doc/src/ets.xml +++ b/lib/stdlib/doc/src/ets.xml @@ -1495,17 +1495,37 @@ is_integer(X), is_integer(Y), X + Y < 4711]]> Match and replace objects atomically in an ETS table

Matches the objects in the table Tab using a - match specification. If - an object is matched, the existing object is replaced with - the match specification result, which must retain - the original key or the operation will fail with badarg.

+ match specification. For each + matched object, the existing object is replaced with + the match specification result.

+

The match-and-replace operation for each individual object is guaranteed to be + atomic and isolated. The + select_replace table iteration as a whole, like all other select functions, + does not give such guarantees.

+

The match specifiction must be guaranteed to retain the key + of any matched object. If not, select_replace will fail with badarg + without updating any objects.

For the moment, due to performance and semantic constraints, tables of type bag are not yet supported.

The function returns the total number of replaced objects.

- -

The match/replacement operation atomicity scope is limited - to each individual object.

-
+

Example

+

For all 2-tuples with a list in second position, add atom 'marker' first in the list:

+
+1> T = ets:new(x,[]), ets:insert(T, {key, [1, 2, 3]}).
+true
+2> MS = ets:fun2ms(fun({K, L}) when is_list(L) -> {K, [marker | L]} end).
+[{{'$1','$2'},[{is_list,'$2'}],[{{'$1',[marker|'$2']}}]}]
+3> ets:select_replace(T, MS).
+1
+4> ets:tab2list(T).
+[{key,[marker,1,2,3]}]
+	
+

A generic single object compare-and-swap operation:

+
+[Old] = ets:lookup(T, Key),
+New = update_object(Old),
+Success = (1 =:= ets:select_replace(T, [{Old, [], [{const, New}]}])),
+	
-- cgit v1.2.3