[erlang-questions] update_counter on steroids

Ulf Wiger ulf@REDACTED
Wed Aug 7 13:39:11 CEST 2013

There was some discussion recently on teaching update_counter some new tricks.

Here is a suggestion:

Right now, the function takes (Tab, Key, UpOp | [UpOp]), where
  UpOp ::== {Pos, Incr} | {Pos, Incr, Threshold, WrapTo}

I'd like to save the result of an operation in a temporary variable.

An atomic reset, for example. (let's say counter c1 has the value 17):

ets:update_counter(counters, c1, [{2, 0, '$1'}, {2, {'-', '$1'}}]) ->
  [17, 0]

(Increment by 0 means we read the existing value, just like today).

Why use this instead of simply ets:insert/2? Well, for one thing, we get the old value back, so it's an atomic read-reset.

Sum counter:

ets:update_counter(counters, c2, [{2,0,'$1'}, {3,0,'$2'}, {4, {'+', '$1', '$2'}}])

Wrap with parameterized threshold and reset value:

ets:update_counter(counters, c3, [{3,0,'$1'}, {4,0,'$2'}, {2, Incr, '$1', '$2'}])

This assumes the following changes:

- A number of temp variables, like in match specs.
- A 3-tuple  {Pos, Incr, SaveTo}, where SaveTo is a variable name (e.g. '$1')
- A 5-tuple  {Pos, Incr, Threshold, WrapTo, SaveTo}
- The possibility to use, wherever an integer() is expected
  VariableName | {UnaryOp, VariableName} | {BinaryOp, Var1, Var2}

We could also use this to e.g. store a value together with an increment operation. A reset with timestamp:

TS = timestamp(),  % in milliseconds
ets:update_counter(counters, c4, [{2, 0, '$1'}, {2, {'-', '$1'}, {3, 0, '$2'}, {3, {'-', TS, '$2'}}])

…a bit bizarre perhaps, but still.


Ulf W

Ulf Wiger, Co-founder & Developer Advocate, Feuerlabs Inc.

More information about the erlang-questions mailing list