Add with-acquired blocks to code that needs it
This commit is contained in:
parent
fb3b95977f
commit
6bc907e720
1 changed files with 38 additions and 24 deletions
|
|
@ -31,8 +31,6 @@
|
||||||
ResourceScope
|
ResourceScope
|
||||||
SegmentAllocator)))
|
SegmentAllocator)))
|
||||||
|
|
||||||
;; TODO(Joshua): Ensure all the serdes acquire the scopes they use
|
|
||||||
|
|
||||||
(defn stack-scope
|
(defn stack-scope
|
||||||
"Constructs a new scope for use only in this thread.
|
"Constructs a new scope for use only in this thread.
|
||||||
|
|
||||||
|
|
@ -104,15 +102,19 @@
|
||||||
(.keepAlive ^ResourceScope source ^ResourceScope target))
|
(.keepAlive ^ResourceScope source ^ResourceScope target))
|
||||||
|
|
||||||
(defmacro with-acquired
|
(defmacro with-acquired
|
||||||
"Acquires a `scope` to ensure it will not be released until the `body` completes.
|
"Acquires one or more `scopes` until the `body` completes.
|
||||||
|
|
||||||
This is only necessary to do on shared scopes, however if you are operating on
|
This is only necessary to do on shared scopes, however if you are operating on
|
||||||
an arbitrary passed scope, it is best practice to wrap code that interacts
|
an arbitrary passed scope, it is best practice to wrap code that interacts
|
||||||
with it wrapped in this."
|
with it wrapped in this."
|
||||||
[scope & body]
|
{:style/indent 1}
|
||||||
|
[scopes & body]
|
||||||
`(with-open [scope# (stack-scope)]
|
`(with-open [scope# (stack-scope)]
|
||||||
(keep-alive scope# ~scope)
|
(run! (partial keep-alive scope#) ~scopes)
|
||||||
~@body))
|
~@body))
|
||||||
|
(s/fdef with-acquired
|
||||||
|
:args (s/cat :scopes any?
|
||||||
|
:body (s/* any?)))
|
||||||
|
|
||||||
(defn address-of
|
(defn address-of
|
||||||
"Gets the address of a given segment.
|
"Gets the address of a given segment.
|
||||||
|
|
@ -176,14 +178,16 @@
|
||||||
(defn copy-segment
|
(defn copy-segment
|
||||||
"Copies the content to `dest` from `src`"
|
"Copies the content to `dest` from `src`"
|
||||||
[dest src]
|
[dest src]
|
||||||
(.copyFrom ^MemorySegment dest ^MemorySegment src))
|
(with-acquired (map segment-scope [src dest])
|
||||||
|
(.copyFrom ^MemorySegment dest ^MemorySegment src)))
|
||||||
|
|
||||||
(defn clone-segment
|
(defn clone-segment
|
||||||
"Clones the content of `segment` into a new segment of the same size."
|
"Clones the content of `segment` into a new segment of the same size."
|
||||||
([segment] (clone-segment segment (connected-scope)))
|
([segment] (clone-segment segment (connected-scope)))
|
||||||
([segment scope]
|
([segment scope]
|
||||||
|
(with-acquired [(segment-scope segment) scope]
|
||||||
(doto ^MemorySegment (alloc (.byteSize ^MemorySegment segment) scope)
|
(doto ^MemorySegment (alloc (.byteSize ^MemorySegment segment) scope)
|
||||||
(copy-segment segment))))
|
(copy-segment segment)))))
|
||||||
|
|
||||||
(defn slice-segments
|
(defn slice-segments
|
||||||
"Constructs a lazy seq of `size`-length memory segments, sliced from `segment`."
|
"Constructs a lazy seq of `size`-length memory segments, sliced from `segment`."
|
||||||
|
|
@ -318,9 +322,10 @@
|
||||||
[obj type scope]
|
[obj type scope]
|
||||||
(when-not (null? obj)
|
(when-not (null? obj)
|
||||||
(if (sequential? type)
|
(if (sequential? type)
|
||||||
|
(with-acquired [scope]
|
||||||
(let [segment (alloc-instance (second type) scope)]
|
(let [segment (alloc-instance (second type) scope)]
|
||||||
(serialize-into obj (second type) segment scope)
|
(serialize-into obj (second type) segment scope)
|
||||||
(address-of segment))
|
(address-of segment)))
|
||||||
obj)))
|
obj)))
|
||||||
|
|
||||||
(defmulti serialize-into
|
(defmulti serialize-into
|
||||||
|
|
@ -333,7 +338,10 @@
|
||||||
override [[c-layout]].
|
override [[c-layout]].
|
||||||
|
|
||||||
For any other type, this will serialize it as [[serialize*]] before writing
|
For any other type, this will serialize it as [[serialize*]] before writing
|
||||||
the result value into the `segment`."
|
the result value into the `segment`.
|
||||||
|
|
||||||
|
Implementations of this should be inside a [[with-acquired]] block for the
|
||||||
|
`scope` if they perform multiple memory operations."
|
||||||
(fn
|
(fn
|
||||||
#_{:clj-kondo/ignore [:unused-binding]}
|
#_{:clj-kondo/ignore [:unused-binding]}
|
||||||
[obj type segment scope]
|
[obj type segment scope]
|
||||||
|
|
@ -342,7 +350,8 @@
|
||||||
(defmethod serialize-into :default
|
(defmethod serialize-into :default
|
||||||
[obj type segment scope]
|
[obj type segment scope]
|
||||||
(if-some [prim-layout (primitive-type type)]
|
(if-some [prim-layout (primitive-type type)]
|
||||||
(serialize-into (serialize* obj type scope) prim-layout segment scope)
|
(with-acquired [(segment-scope scope) scope]
|
||||||
|
(serialize-into (serialize* obj type scope) prim-layout segment scope))
|
||||||
(throw (ex-info "Attempted to serialize an object to a type that has not been overriden"
|
(throw (ex-info "Attempted to serialize an object to a type that has not been overriden"
|
||||||
{:type type
|
{:type type
|
||||||
:object obj}))))
|
:object obj}))))
|
||||||
|
|
@ -403,7 +412,10 @@
|
||||||
"Deserializes the given segment into a Clojure data structure.
|
"Deserializes the given segment into a Clojure data structure.
|
||||||
|
|
||||||
For types that serialize to primitives, a default implementation will
|
For types that serialize to primitives, a default implementation will
|
||||||
deserialize the primitive before calling [[deserialize*]]."
|
deserialize the primitive before calling [[deserialize*]].
|
||||||
|
|
||||||
|
Implementations of this should be inside a [[with-acquired]] block for the the
|
||||||
|
`segment`'s scope if they perform multiple memory operations."
|
||||||
(fn
|
(fn
|
||||||
#_{:clj-kondo/ignore [:unused-binding]}
|
#_{:clj-kondo/ignore [:unused-binding]}
|
||||||
[segment type]
|
[segment type]
|
||||||
|
|
@ -412,9 +424,10 @@
|
||||||
(defmethod deserialize-from :default
|
(defmethod deserialize-from :default
|
||||||
[segment type]
|
[segment type]
|
||||||
(if-some [prim (primitive-type type)]
|
(if-some [prim (primitive-type type)]
|
||||||
|
(with-acquired [(segment-scope segment)]
|
||||||
(-> segment
|
(-> segment
|
||||||
(deserialize-from prim)
|
(deserialize-from prim)
|
||||||
(deserialize* type))
|
(deserialize* type)))
|
||||||
(throw (ex-info "Attempted to deserialize a non-primitive type that has not been overriden"
|
(throw (ex-info "Attempted to deserialize a non-primitive type that has not been overriden"
|
||||||
{:type type
|
{:type type
|
||||||
:segment segment}))))
|
:segment segment}))))
|
||||||
|
|
@ -453,8 +466,9 @@
|
||||||
|
|
||||||
(defmethod deserialize-from ::pointer
|
(defmethod deserialize-from ::pointer
|
||||||
[segment type]
|
[segment type]
|
||||||
|
(with-acquired [(segment-scope segment)]
|
||||||
(cond-> (MemoryAccess/getAddress segment)
|
(cond-> (MemoryAccess/getAddress segment)
|
||||||
(sequential? type) (deserialize* type)))
|
(sequential? type) (deserialize* type))))
|
||||||
|
|
||||||
(defmulti deserialize*
|
(defmulti deserialize*
|
||||||
"Deserializes a primitive object into a Clojure data structure.
|
"Deserializes a primitive object into a Clojure data structure.
|
||||||
|
|
@ -490,15 +504,15 @@
|
||||||
a segment."
|
a segment."
|
||||||
[obj type]
|
[obj type]
|
||||||
(when-not (identical? ::void type)
|
(when-not (identical? ::void type)
|
||||||
((if (primitive-type type)
|
(if (primitive-type type)
|
||||||
deserialize*
|
(deserialize* obj type)
|
||||||
deserialize-from)
|
(deserialize-from obj type))))
|
||||||
obj type)))
|
|
||||||
|
|
||||||
(defn seq-of
|
(defn seq-of
|
||||||
"Constructs a lazy sequence of `type` elements deserialized from `segment`."
|
"Constructs a lazy sequence of `type` elements deserialized from `segment`."
|
||||||
[type segment]
|
[type segment]
|
||||||
(map #(deserialize % type) (slice-segments segment (size-of type))))
|
(with-acquired [(segment-scope segment)]
|
||||||
|
(map #(deserialize % type) (slice-segments segment (size-of type)))))
|
||||||
|
|
||||||
;;; C String type
|
;;; C String type
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue