Synchronized Data Structures.

To use the bindings from this module:

(import :std/misc/sync)

make-sync-hash

(make-sync-hash ht) -> sync-hash

  ht := regular non-synced hash-table

Wraps ht, a regular hash-table, and returns a synced variant that supports thread-safe table operations by implicitly locking.

Note: It's discouraged to modify the unwrapped, non-thread-safe ht after this point.

Examples:

> (import :gerbil/gambit/threads :std/iter :std/srfi/1)
> (def (increment! sht)
    (for (x (in-range 1000))
      (sync-hash-do sht (cut hash-update! <> x 1+ 0))))

> (def sht (make-sync-hash (make-hash-table-eqv)))
> (def threads (for/collect (n (in-range 16))
                 (spawn-thread (cut increment! sht))))
> (for-each thread-join! threads)
> (sync-hash-do sht
    (lambda (ht)
      (every (cut = 16 <>)
             (hash-values ht))))
#t

sync-hash?

(sync-hash? sht) -> boolean

  sht := sync-hash to check

Returns #t if sht is a sync-hash, #f otherwise.

Synced variant of hash? and hash-table?.

Examples:

> (import :std/sugar)
> (sync-hash? (make-sync-hash (hash)))
#t

> (sync-hash? (make-hash-table))
#f

sync-hash-ref

(sync-hash-ref sht key default) -> any | default

  sht     := sync-hash to check
  key     := key to loop up in sht
  default := non-optional default value when key not present

Returns the value bound to key in sht, defaulting to default if no such value was bound.

Synced variant of hash-ref.

Examples:

> (import :std/sugar)
> (def sht (make-sync-hash (hash (एक 1) (दस 10) (सौ 100))))
> (sync-hash-ref sht 'दस 0)
10
> (sync-hash-ref sht 'सहस्र 0)
0
> (sync-hash-ref sht 10 'NONE)
NONE

sync-hash-get

(sync-hash-get sht key) -> any | #f

  sht := sync-hash to check
  key := key to loop up in sht

Same as (sync-hash-ref sht key #f).

Synced variant of hash-get.

Examples:

> (import :std/sugar)
> (def sht (make-sync-hash (hash ( 1) ( 10) ( 100))))
> (sync-hash-get sht '十)
10
> (sync-hash-get sht '千)
#f
> (sync-hash-get sht 10)
#f

sync-hash-put!

(sync-hash-put! sht key val) -> unspecified

  sht      := sync-hash to modify
  key, val := key-value pair to add to sht

Binds key to val in sht.

Synced variant of hash-put!.

Examples:

> (import :std/sugar)
> (make-sync-hash (hash))
#<sync-hash #77>
> (sync-hash-put! #77 #\a [1 2 3])
> (sync-hash-put! #77 'a  [4 5 6])
> (sync-hash-put! #77 "a" [7 8 9])
> (sync-hash-do #77 (cut hash-values <>))
((1 2 3) (4 5 6) (7 8 9))

sync-hash-remove!

(sync-hash-remove! sht key) -> void

  sht := sync-hash to modify
  key := key to look up in sht

Removes sht's binding for key.

Synced variant of hash-remove!.

Examples:

> (import :std/sugar)
> (let (sht (make-sync-hash (hash (a 10) (b 20) (c 30) (d 40))))
    (sync-hash-remove! sht 'b)
    (sync-hash-remove! sht 'e)    ; nothing happens
    (sync-hash-do sht
      (lambda (ht) (hash-for-each (cut displayln <> " -> " <>) ht))))
a -> 10
d -> 40
c -> 30

sync-hash-key?

(sync-hash-key? sht key) -> boolean

  sht := sync-hash to check
  key := key to look up in sht

Returns #t if sht has a binding for key, #f otherwise.

Synced variant of hash-key?.

Examples:

> (def sht (make-sync-hash (list->hash-table [[1 . #\a] [2 . #\b] [3 . #\c]])))
> (sync-hash-key? sht 1)
#t
> (sync-hash-key? sht 3)
#t
> (sync-hash-key? sht 4)
#f

sync-hash-do

(sync-hash-do sht proc) -> any

  sht  := sync-hash to iterate or modify
  proc := procedure handling internal hash-table

Allows thread-safe access to the unwrapped regular hash-table of sht by passing it to proc within an implicitly locked scope. Returns whatever proc is returning.

Examples:

> (import :std/sugar)
> (def sht (make-sync-hash (hash (A0 160) (B1 177) (C2 194) (D3 211) (E4 228))))
> (sync-hash-do sht
    (lambda (ht)
      (hash-fold (lambda (k v i) (+ v i)) 0 ht)))
970
> (sync-hash-do sht (cut hash-put! <> 'C2 0))
> (sync-hash-get sht 'C2)
0
> (sync-hash-do sht hash->list)
((A0 . 160) (B1 . 177) (D3 . 211) (E4 . 228) (C2 . 0))
> (sync-hash-do sht (lambda (ht) (apply max (hash-values ht))))
228