|
4 | 4 | (:refer-clojure :exclude [await]) |
5 | 5 | (:import [System.Threading.Tasks Task])) |
6 | 6 |
|
7 | | -(set! *warn-on-reflection* true) |
8 | 7 |
|
9 | 8 | ;; ── Internal helpers ────────────────────────────────────────────────── |
10 | 9 |
|
| 10 | +; This would get a reflection warning, so we don't turn on *warn-on-reflection* until after. |
| 11 | +; We WANT a reflection warning -- we need the DLR callsite mechanism on the call to .GetAwaiter. |
| 12 | +; If we tag the task parameter as ^Task, we always pick up Task.GetAwaiter(), even for generic Task<TResult> tasks. |
| 13 | +; That just does not work. |
| 14 | + |
11 | 15 | (defn- task-result |
12 | 16 | "Extracts the result from a completed Task<T> via its typed awaiter. |
13 | 17 | Uses GetAwaiter().GetResult() which unwraps exceptions cleanly |
14 | 18 | (no AggregateException wrapping unlike .Result). |
15 | 19 | Returns nil for non-generic Task (void)." |
16 | | - [^Task task] |
17 | | - (let [t (.GetType task)] |
| 20 | + [task] |
| 21 | + (let [t (.GetType ^Object task)] |
18 | 22 | (when (.IsGenericType t) |
19 | 23 | (let [^Type type-arg (aget (.GetGenericArguments t) 0)] |
20 | 24 | (when-not (= "VoidTaskResult" (.Name type-arg)) |
21 | | - (let [awaiter (.Invoke (.GetMethod t "GetAwaiter" Type/EmptyTypes) task nil)] |
22 | | - (.Invoke (.GetMethod (.GetType ^Object awaiter) "GetResult" Type/EmptyTypes) |
23 | | - awaiter nil))))))) |
| 25 | + (-> task .GetAwaiter .GetResult)))))) |
| 26 | + |
| 27 | + |
| 28 | +(set! *warn-on-reflection* true) |
| 29 | + |
24 | 30 |
|
25 | 31 | ;; ── Macros (only these two require macro status) ────────────────────── |
26 | 32 |
|
|
127 | 133 | (t/result (t/->task 42)) ;=> 42 |
128 | 134 | (t/result (t/completed-task)) ;=> nil |
129 | 135 | (t/result (t/async (t/await (t/delay-task 100)) \"done\")) ;=> \"done\"" |
130 | | - [^Task task] |
131 | | - ;; Block until complete. Non-generic GetResult() handles void tasks |
132 | | - ;; and throws inner exception (not AggregateException) on fault. |
133 | | - (-> task .GetAwaiter .GetResult) |
134 | | - ;; For Task<T>, extract the typed result via the generic awaiter. |
| 136 | + [task] |
135 | 137 | (task-result task)) |
0 commit comments