# sharedtables

- Manual
- Standard library
- Index

Search:
Group by:

Shared table support for Nim. Use plain old non GC'ed keys and values or you'll be in trouble. Uses a single lock to protect the table, lockfree implementations welcome but if lock contention is so high that you need a lockfree hash table, you're doing it wrong.

# Imports

hashes, math, locks

# Types

    SharedTable[A; B] = object
      data: KeyValuePairSeq[A, B]
      counter, dataLen: int
      lock: Lock

  generic hash SharedTable Source Edit

# Procs

    proc mget[A, B](t: var SharedTable[A, B]; key: A): var B

  retrieves the value at `t[key]`. The value can be modified. If `key` is not in `t`, the `KeyError` exception is raised. Source Edit

    proc mgetOrPut[A, B](t: var SharedTable[A, B]; key: A; val: B): var B

  retrieves value at `t[key]` or puts `val` if not present, either way returning a value which can be modified. Note: This is inherently unsafe in the context of multi-threading since it returns a pointer to `B`. Source Edit

    proc hasKeyOrPut[A, B](t: var SharedTable[A, B]; key: A; val: B): bool

  returns true iff `key` is in the table, otherwise inserts `value`. Source Edit

    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:

  1. `key` - the current key, if it exists, or the key passed to `withKey` otherwise;
  2. `val` - the current value, if the key exists, or default value of the type otherwise;
  3. `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:

      # 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

  Source Edit

    proc `[]=`[A, B](t: var SharedTable[A, B]; key: A; val: B)

  puts a (key, value)-pair into `t`. Source Edit

    proc add[A, B](t: var SharedTable[A, B]; key: A; val: B)

  puts a new (key, value)-pair into `t` even if `t[key]` already exists. This can introduce duplicate keys into the table! Source Edit

    proc del[A, B](t: var SharedTable[A, B]; key: A)

  deletes `key` from hash table `t`. Source Edit

    proc init[A, B](t: var SharedTable[A, B]; initialSize = 64)

  creates a new hash table that is empty.

  This proc must be called before any other usage of `t`.

  `initialSize` needs to be a power of two. If you need to accept runtime values for this you could use the `nextPowerOfTwo` proc from the math module or the `rightSize` proc from this module.

  Source Edit

    proc deinitSharedTable[A, B](t: var SharedTable[A, B])

  Source Edit

    proc initSharedTable[A, B](initialSize = 64): SharedTable[A, B] {...}{.
        deprecated: "use \'init\' instead".}

  Deprecated: use 'init' instead
  This is not posix compliant, may introduce undefined behavior. Source Edit

# Templates

    template withValue[A; B](t: var SharedTable[A, B]; key: A; value, body: untyped)

  retrieves the value at `t[key]`. `value` can be modified in the scope of the `withValue` call.

      sharedTable.withValue(key, value) do:
        # block is executed only if ``key`` in ``t``
        # value is threadsafe in block
        value.name = "username"
        value.uid = 1000

  Source Edit

    template withValue[A; B](t: var SharedTable[A, B]; key: A; value, body1, body2: untyped)

  retrieves the value at `t[key]`. `value` can be modified in the scope of the `withValue` call.

      sharedTable.withValue(key, value) do:
        # block is executed only if ``key`` in ``t``
        # value is threadsafe in block
        value.name = "username"
        value.uid = 1000
      do:
        # block is executed when ``key`` not in ``t``
        raise newException(KeyError, "Key not found")

  Source Edit