-
-
Notifications
You must be signed in to change notification settings - Fork 57
/
util.cljc
125 lines (105 loc) · 2.86 KB
/
util.cljc
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
119
120
121
122
123
124
;; This Source Code Form is subject to the terms of the Mozilla Public
;; License, v. 2.0. If a copy of the MPL was not distributed with this
;; file, You can obtain one at http://mozilla.org/MPL/2.0/.
;;
;; Copyright (c) Andrey Antukh <niwi@niwi.nz>
(ns promesa.util
(:require [promesa.protocols :as pt])
#?(:clj
(:import
java.lang.reflect.Method
java.time.Duration
java.util.concurrent.CompletionException
java.util.concurrent.CompletionStage
java.util.concurrent.CountDownLatch
java.util.concurrent.locks.ReentrantLock
;; java.util.function.BiConsumer
;; java.util.function.BiFunction
;; java.util.function.Consumer
;; java.util.function.Function
;; java.util.function.Supplier
)))
#?(:clj (set! *warn-on-reflection* true))
#?(:clj
(extend-protocol clojure.core/Inst
Duration
(inst-ms* [v] (.toMillis ^Duration v))))
#?(:clj
(deftype Supplier [f]
java.util.function.Supplier
(get [_] (f))))
#?(:clj
(deftype Function [f]
java.util.function.Function
(apply [_ v]
(f v))))
#?(:clj
(def f-identity (->Function identity)))
#?(:clj
(defn unwrap-completion-stage
{:no-doc true}
[it]
(.thenCompose ^CompletionStage it
^java.util.function.Function f-identity)))
#?(:clj
(defn unwrap-completion-exception
{:no-doc true}
[cause]
(if (instance? CompletionException cause)
(.getCause ^CompletionException cause)
cause)))
#?(:clj
(deftype Function2 [f]
java.util.function.BiFunction
(apply [_ r e]
(f r (unwrap-completion-exception e)))))
#?(:clj
(deftype Consumer2 [f]
java.util.function.BiConsumer
(accept [_ r e]
(f r (unwrap-completion-exception e)))))
(defn handler
"Create a handler, mainly for combine two separate functions
into a single callbale."
[fv fc]
(fn [v c]
(if c (fc c) (fv v))))
(defn has-method?
{:no-doc true}
[klass name]
(let [methods (into #{}
(map (fn [method] (.getName ^Method method)))
(.getDeclaredMethods ^Class klass))]
(contains? methods name)))
(defn maybe-deref
{:no-doc true}
[o]
(if (delay? o)
(deref o)
o))
(defn mutex
{:no-doc true}
[]
#?(:clj
(let [m (ReentrantLock.)]
(reify
pt/ILock
(-lock! [_] (.lock m))
(-unlock! [_] (.unlock m))))
:cljs
(reify
pt/ILock
(-lock! [_])
(-unlock! [_]))))
(defn try*
{:no-doc true}
[f on-error]
(try (f) (catch #?(:clj Throwable :cljs :default) e (on-error e))))
;; http://clj-me.cgrand.net/2013/09/11/macros-closures-and-unexpected-object-retention/
;; Explains the use of ^:once metadata
(defmacro ignoring
[& exprs]
`(try* (^:once fn* [] ~@exprs) (constantly nil)))
(defmacro try!
[& exprs]
`(try* (^:once fn* [] ~@exprs) identity))