-
Notifications
You must be signed in to change notification settings - Fork 297
/
zerocopy.clj
119 lines (99 loc) · 3.95 KB
/
zerocopy.clj
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
(ns io.pedestal.http.request.zerocopy
(:require [io.pedestal.http.request :as request])
(:import (java.util Map)))
;; Containers optimize the data structure behind request objects,
;; for efficient time and space properties.
;; For Jetty, the base request information is stored in an array, with a
;; a tree of indexes for key pieces of data -- https://webtide.com/jetty-9-goes-fast-with-mechanical-sympathy/
;; This request type calls functions on lookup, which can close-over zero/low-copy datastructures.
;; No data is copied or cached, but all lookups involve an additional stackframe
;; (which may be optimized out by the JIT)
;; This request doesn't copy any data from the container,
;; and proxies all Ring-like map lookups to the containers request data structure.
;; Care is given to uphold all value semantics.
(deftype CallThroughRequest [base-request ;; This should be a ContainerRequest
^clojure.lang.IPersistentMap user-data]
clojure.lang.ILookup
;; Upon lookup, transparently dispatch to the container's request.
(valAt [this k]
(user-data k ((request/ring-dispatch k request/nil-fn) base-request)))
(valAt [this k not-found]
(let [v (user-data k ::not-found)]
(if (= v ::not-found)
(let [v (request/ring-dispatch k ::not-found)]
(if (= v ::not-found)
not-found
(v base-request)))
v)))
request/ProxyDatastructure
(realized [this]
(persistent!
(reduce-kv (fn [m k v]
(assoc! m k (v base-request)))
(transient user-data)
request/ring-dispatch)))
clojure.lang.Associative
(containsKey [this k]
(or (contains? request/ring-dispatch k)
(contains? user-data k)))
(entryAt [this k]
(or (.entryAt user-data k)
(and (contains? request/ring-dispatch k)
(clojure.lang.MapEntry. k ((request/ring-dispatch k) base-request)))
nil))
(assoc [this k v]
(CallThroughRequest. base-request (assoc user-data k v)))
clojure.lang.IFn
(invoke [this k] (.valAt this k))
(invoke [this k default] (.valAt this k default))
clojure.lang.IPersistentMap
(without [this k]
(dissoc (request/realized this) k))
clojure.lang.Counted
(count [this] (unchecked-add (if (= base-request nil) 0 (count request/ring-dispatch))
(count user-data)))
clojure.lang.IPersistentCollection
(cons [this o] (CallThroughRequest. base-request (.cons user-data o)))
(empty [this] (CallThroughRequest. nil {}))
;; Equality is java.util.Map equality, against the fully realized map
(equiv [this o]
(.equals this o))
clojure.lang.Seqable
(seq [this]
(seq (request/realized this)))
java.lang.Iterable
(iterator [this]
(let [it ^java.util.Iterator (.iterator ^java.lang.Iterable (seq this))]
(reify java.util.Iterator
(hasNext [_] (.hasNext it))
(next [_] (.next it))
(remove [_] (throw (UnsupportedOperationException.))))))
java.util.Map
(containsValue [this v]
(contains? (set (.values this)) v))
(entrySet [this]
(.entrySet ^Map (request/realized this)))
;; Equality is java.util.Map equality, against the fully realized map
(equals [this o]
(if (instance? Map o)
(= (.entrySet ^Map this) (.entrySet ^Map o))
false))
(get [this k]
(.valAt this k))
(isEmpty [this]
(and (= base-request nil) (empty? user-data)))
(keySet [this]
(.keySet ^Map (request/realized this)))
(size [this]
(.count this))
(values [this]
(vals (request/realized this)))
(clear [this] (throw (UnsupportedOperationException.)))
(put [this k v] (throw (UnsupportedOperationException.)))
(putAll [this m] (throw (UnsupportedOperationException.)))
(remove [this k] (throw (UnsupportedOperationException.))))
(defn call-through-request
([container-req]
(->CallThroughRequest container-req {}))
([container-req override-map]
(->CallThroughRequest container-req override-map)))