Skip to content

Commit 2ec6d37

Browse files
committed
Missed adding this file - it is in the release, however.
1 parent e95441f commit 2ec6d37

File tree

2 files changed

+68
-0
lines changed

2 files changed

+68
-0
lines changed

Diff for: project.clj

+1
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@
5959
tech.v3.datatype.ffi
6060
tech.v3.datatype.ffi.clang
6161
tech.v3.datatype.struct
62+
tech.v3.datatype.locker
6263
tech.v3.tensor.dimensions
6364
tech.v3.tensor.color-gradients
6465
tech.v3.datatype.reductions

Diff for: src/tech/v3/datatype/locker.clj

+67
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
(ns tech.v3.datatype.locker
2+
"Threadsafe access to a key-value map. Unlike atoms and swap! your
3+
update/initialization functions are never ran in parallel which helps if, for instance,
4+
initialization is a long running, memory intensive operation there will only be one
5+
running even if multiple threads request a value simultaneously.
6+
7+
```clojure
8+
user> (require '[tech.v3.datatype.locker :as locker])
9+
nil
10+
user> (locker/update! ::latest (fn [k v]
11+
(println (format \"k is %s v is %s\" k v))
12+
::updated))
13+
k is :user/latest v is null
14+
:user/updated
15+
user> (locker/update! ::latest (fn [k v]
16+
(println (format \"k is %s v is %s\" k v))
17+
::updated))
18+
k is :user/latest v is :user/updated
19+
:user/updated
20+
```"
21+
(:require [tech.v3.datatype.jvm-map :as jvm-map])
22+
(:import [java.util.concurrent ConcurrentHashMap]))
23+
24+
25+
(set! *warn-on-reflection* true)
26+
27+
28+
(defonce ^{:tag ConcurrentHashMap} locker* (delay (ConcurrentHashMap.)))
29+
(defn locker ^ConcurrentHashMap [] @locker*)
30+
31+
32+
(defn remove!
33+
"Remove a key - returns the value if any that existed in that location."
34+
[key]
35+
(.remove (locker) key))
36+
37+
38+
(defn compute-if-absent!
39+
"Compute a new value if non exists for this key. Key cannot be nil.
40+
init-fn will only ever be called once and is passed the key as its first
41+
argument."
42+
[key init-fn]
43+
(jvm-map/compute-if-absent! (locker) key init-fn))
44+
45+
46+
(defn compute-if-present!
47+
"Compute a new value if one already exists for this key. Key cannot be nil.
48+
update-fn is passed the key and the preexisting value."
49+
[key update-fn]
50+
(jvm-map/compute-if-present! (locker) key update-fn))
51+
52+
53+
(defn exists?
54+
[key]
55+
(.containsKey (locker) key))
56+
57+
58+
(defn update!
59+
"Update a value. update-fn gets passed the key and the value already present (if any)."
60+
[key update-fn]
61+
(jvm-map/compute! (locker) key update-fn))
62+
63+
64+
(defn value
65+
([key missing-value]
66+
(.getOrDefault (locker) key missing-value))
67+
([key] (value key nil)))

0 commit comments

Comments
 (0)