diff options
author | Ruslan Mustakov <endragor@users.noreply.github.com> | 2017-03-02 21:31:30 +0700 |
---|---|---|
committer | Andreas Rumpf <rumpf_a@web.de> | 2017-03-02 15:31:30 +0100 |
commit | a81247dcbe95eaac8338e478d8837cbcf57a0f3e (patch) | |
tree | cf7d86e6e19cf16e9149885a2ac81c4f2f09a2e7 /lib | |
parent | e2567e2e03c72929cbdfbf59933b4f35868b9626 (diff) | |
download | Nim-a81247dcbe95eaac8338e478d8837cbcf57a0f3e.tar.gz |
Add compute proc for SharedTable (#5385)
Diffstat (limited to 'lib')
-rw-r--r-- | lib/pure/collections/sharedtables.nim | 46 | ||||
-rw-r--r-- | lib/pure/collections/tableimpl.nim | 9 |
2 files changed, 52 insertions, 3 deletions
diff --git a/lib/pure/collections/sharedtables.nim b/lib/pure/collections/sharedtables.nim index 28509caa1..de573bcb2 100644 --- a/lib/pure/collections/sharedtables.nim +++ b/lib/pure/collections/sharedtables.nim @@ -130,6 +130,52 @@ proc hasKeyOrPut*[A, B](t: var SharedTable[A, B], key: A, val: B): bool = withLock t: hasKeyOrPutImpl(enlarge) +proc withKey*[A, B](t: var SharedTable[A, B], key: A, + mapper: proc(key: A, val: var B, pairExists: var bool)) = + ## Computes a new mapping for the ``key`` with the specified ``mapper`` + ## procedure. + ## + ## The ``mapper`` takes 3 arguments: + ## #. ``key`` - the current key, if it exists, or the key passed to + ## ``withKey`` otherwise; + ## #. ``val`` - the current value, if the key exists, or default value + ## of the type otherwise; + ## #. ``pairExists`` - ``true`` if the key exists, ``false`` otherwise. + ## The ``mapper`` can can modify ``val`` and ``pairExists`` values to change + ## the mapping of the key or delete it from the table. + ## When adding a value, make sure to set ``pairExists`` to ``true`` along + ## with modifying the ``val``. + ## + ## The operation is performed atomically and other operations on the table + ## will be blocked while the ``mapper`` is invoked, so it should be short and + ## simple. + ## + ## Example usage: + ## + ## .. code-block:: nim + ## + ## # If value exists, decrement it. + ## # If it becomes zero or less, delete the key + ## t.withKey(1'i64) do (k: int64, v: var int, pairExists: var bool): + ## if pairExists: + ## dec v + ## if v <= 0: + ## pairExists = false + withLock t: + var hc: Hash + var index = rawGet(t, key, hc) + + var pairExists = index >= 0 + if pairExists: + mapper(t.data[index].key, t.data[index].val, pairExists) + if not pairExists: + delImplIdx(t, index) + else: + var val: B + mapper(key, val, pairExists) + if pairExists: + maybeRehashPutImpl(enlarge) + proc `[]=`*[A, B](t: var SharedTable[A, B], key: A, val: B) = ## puts a (key, value)-pair into `t`. withLock t: diff --git a/lib/pure/collections/tableimpl.nim b/lib/pure/collections/tableimpl.nim index 5e871f08b..c0d45c392 100644 --- a/lib/pure/collections/tableimpl.nim +++ b/lib/pure/collections/tableimpl.nim @@ -120,9 +120,7 @@ template default[T](t: typedesc[T]): T = var v: T v -template delImpl() {.dirty.} = - var hc: Hash - var i = rawGet(t, key, hc) +template delImplIdx(t, i) = let msk = maxHash(t) if i >= 0: dec(t.counter) @@ -145,6 +143,11 @@ template delImpl() {.dirty.} = else: shallowCopy(t.data[j], t.data[i]) # data[j] will be marked EMPTY next loop +template delImpl() {.dirty.} = + var hc: Hash + var i = rawGet(t, key, hc) + delImplIdx(t, i) + template clearImpl() {.dirty.} = for i in 0 .. <t.data.len: when compiles(t.data[i].hcode): # CountTable records don't contain a hcode |