|
58 | 58 | .iterator
|
59 | 59 | iterator-seq
|
60 | 60 | (map
|
61 |
| - (fn [^Downstream d] |
62 |
| - [(.description d) (.sink d)])))))) |
| 61 | + (fn [^Downstream dwn] |
| 62 | + [(.description dwn) (.sink dwn)])))))) |
63 | 63 |
|
64 | 64 | (defn pop-connected! [stream]
|
65 | 65 | (when-let [handle (s/weak-handle stream)]
|
|
76 | 76 | ;;;
|
77 | 77 |
|
78 | 78 | (defn- async-send
|
79 |
| - [^Downstream d msg dsts] |
80 |
| - (let [^IEventSink sink (.sink d)] |
81 |
| - (let [x (if (== (.timeout d) -1) |
| 79 | + "Returns an AsyncPut with the result of calling a non-blocking .put() on a sink. |
| 80 | + If it times out, returns the sink itself as the timeout value." |
| 81 | + [^Downstream dwn msg dsts] |
| 82 | + (let [^IEventSink sink (.sink dwn)] |
| 83 | + (let [x (if (== (.timeout dwn) -1) |
82 | 84 | (.put sink msg false)
|
83 |
| - (.put sink msg false (.timeout d) (if (.downstream? d) sink false)))] |
84 |
| - (AsyncPut. x dsts d (.upstream? d))))) |
| 85 | + (.put sink msg false (.timeout dwn) (if (.downstream? dwn) sink false)))] |
| 86 | + (AsyncPut. x dsts dwn (.upstream? dwn))))) |
85 | 87 |
|
86 | 88 | (defn- sync-send
|
87 |
| - [^Downstream d msg ^CopyOnWriteArrayList dsts ^IEventSink upstream] |
88 |
| - (let [^IEventSink sink (.sink d) |
| 89 | + [^Downstream dwn msg ^CopyOnWriteArrayList dsts ^IEventSink upstream] |
| 90 | + (let [^IEventSink sink (.sink dwn) |
89 | 91 | x (try
|
90 |
| - (if (== (.timeout d) -1) |
| 92 | + (if (== (.timeout dwn) -1) |
91 | 93 | (.put sink msg true)
|
92 |
| - (.put sink msg true (.timeout d) ::timeout)) |
| 94 | + (.put sink msg true (.timeout dwn) ::timeout)) |
93 | 95 | (catch Throwable e
|
94 | 96 | (log/error e "error in message propagation")
|
95 | 97 | (s/close! sink)
|
96 | 98 | false))]
|
97 | 99 | (when (false? x)
|
98 |
| - (.remove dsts d) |
| 100 | + (.remove dsts dwn) |
99 | 101 | (when upstream
|
100 | 102 | (s/close! upstream)))
|
101 |
| - (when (and (identical? ::timeout x) (.downstream? d)) |
| 103 | + (when (and (identical? ::timeout x) (.downstream? dwn)) |
102 | 104 | (s/close! sink))))
|
103 | 105 |
|
104 |
| -(defn- handle-async-put [^AsyncPut x val source] |
| 106 | +(defn- handle-async-put |
| 107 | + "Handle a successful async put" |
| 108 | + [^AsyncPut x val source] |
105 | 109 | (let [d (.deferred x)
|
106 |
| - val (if (instance? IEventSink val) |
| 110 | + val (if (instance? IEventSink val) ; it timed out, in which case the val is set to the sink |
107 | 111 | (do
|
108 | 112 | (s/close! val)
|
109 | 113 | false)
|
110 | 114 | val)]
|
| 115 | + ;; if sink failed or timed out, remove and maybe close source |
111 | 116 | (when (false? val)
|
112 | 117 | (let [^CopyOnWriteArrayList l (.dsts x)]
|
113 | 118 | (.remove l (.dst x))
|
|
125 | 130 | (.remove handle->downstreams (s/weak-handle source)))))
|
126 | 131 |
|
127 | 132 | (defn- async-connect
|
| 133 | + "Connects downstreams to an async source. |
| 134 | +
|
| 135 | + Puts to sync sinks are delayed until all async sinks have been successfully put to" |
128 | 136 | [^IEventSource source
|
129 | 137 | ^CopyOnWriteArrayList dsts]
|
130 | 138 | (let [sync-sinks (LinkedList.)
|
131 |
| - deferreds (LinkedList.) |
| 139 | + put-deferreds (LinkedList.) |
132 | 140 |
|
| 141 | + ;; asynchronously .put to all synchronous sinks, using callbacks and trampolines as needed |
133 | 142 | sync-propagate (fn this [recur-point msg]
|
134 | 143 | (loop []
|
135 |
| - (let [^Downstream d (.poll sync-sinks)] |
136 |
| - (if (nil? d) |
| 144 | + (let [^Downstream dwn (.poll sync-sinks)] |
| 145 | + (if (nil? dwn) |
137 | 146 | recur-point
|
138 |
| - (let [^AsyncPut x (async-send d msg dsts) |
| 147 | + (let [^AsyncPut x (async-send dwn msg dsts) |
139 | 148 | d (.deferred x)
|
140 | 149 | val (d/success-value d ::none)]
|
141 | 150 | (if (identical? val ::none)
|
142 | 151 | (d/on-realized d
|
143 |
| - (fn [v] |
144 |
| - (handle-async-put x v source) |
| 152 | + (fn [val] |
| 153 | + (handle-async-put x val source) |
145 | 154 | (trampoline #(this recur-point msg)))
|
146 | 155 | (fn [e]
|
147 | 156 | (handle-async-error x e source)
|
|
150 | 159 | (handle-async-put x val source)
|
151 | 160 | (recur))))))))
|
152 | 161 |
|
| 162 | + ;; handle all the async puts, using callbacks and trampolines as needed |
| 163 | + ;; then handle all sync puts once asyncs are done |
153 | 164 | async-propagate (fn this [recur-point msg]
|
154 | 165 | (loop []
|
155 |
| - (let [^AsyncPut x (.poll deferreds)] |
| 166 | + (let [^AsyncPut x (.poll put-deferreds)] |
156 | 167 | (if (nil? x)
|
157 | 168 |
|
158 |
| - ;; iterator over sync-sinks |
| 169 | + ;; iterator over sync-sinks when deferreds list is empty |
159 | 170 | (if (.isEmpty sync-sinks)
|
160 | 171 | recur-point
|
161 | 172 | #(sync-propagate recur-point msg))
|
|
197 | 208 | (let [i (.iterator dsts)]
|
198 | 209 | (loop []
|
199 | 210 | (when (.hasNext i)
|
200 |
| - (let [^Downstream d (.next i)] |
201 |
| - (when (.downstream? d) |
202 |
| - (s/close! (.sink d))) |
| 211 | + (let [^Downstream dwn (.next i)] |
| 212 | + (when (.downstream? dwn) |
| 213 | + (s/close! (.sink dwn))) |
203 | 214 | (recur))))))
|
204 | 215 |
|
205 | 216 | (== 1 (.size dsts))
|
|
226 | 237 | :else
|
227 | 238 | (let [i (.iterator dsts)]
|
228 | 239 | (if (not (.hasNext i))
|
229 |
| - |
| 240 | + ;; close source if no downstreams |
230 | 241 | (do
|
231 | 242 | (s/close! source)
|
232 | 243 | (.remove handle->downstreams (s/weak-handle source)))
|
233 | 244 |
|
| 245 | + ;; otherwise: |
| 246 | + ;; 1. add all sync downstreams into a list |
| 247 | + ;; 2. attempt to .put() all async downstreams and collect AsyncPuts in a list |
| 248 | + ;; 3. call async-propagate |
234 | 249 | (do
|
235 | 250 | (loop []
|
236 | 251 | (when (.hasNext i)
|
237 |
| - (let [^Downstream d (.next i)] |
238 |
| - (if (s/synchronous? (.sink d)) |
239 |
| - (.add sync-sinks d) |
240 |
| - (.add deferreds (async-send d msg dsts))) |
| 252 | + (let [^Downstream dwn (.next i)] |
| 253 | + (if (s/synchronous? (.sink dwn)) |
| 254 | + (.add sync-sinks dwn) |
| 255 | + (.add put-deferreds (async-send dwn msg dsts))) |
241 | 256 | (recur))))
|
242 | 257 |
|
243 | 258 | (async-propagate this msg))))))))))
|
244 | 259 |
|
245 | 260 | (defn- sync-connect
|
| 261 | + "Connects downstreams to a sync source" |
246 | 262 | [^IEventSource source
|
247 | 263 | ^CopyOnWriteArrayList dsts]
|
248 | 264 | (utils/future-with (ex/wait-pool)
|
|
259 | 275 | (.remove handle->downstreams (s/weak-handle source))
|
260 | 276 | (loop []
|
261 | 277 | (when (.hasNext i)
|
262 |
| - (let [^Downstream d (.next i)] |
263 |
| - (when (.downstream? d) |
264 |
| - (s/close! (.sink d))))))) |
| 278 | + (let [^Downstream dwn (.next i)] |
| 279 | + (when (.downstream? dwn) |
| 280 | + (s/close! (.sink dwn))))))) |
265 | 281 |
|
266 | 282 | (do
|
267 | 283 | (loop []
|
268 | 284 | (when (.hasNext i)
|
269 |
| - (let [^Downstream d (.next i)] |
270 |
| - (if (s/synchronous? (.sink d)) |
271 |
| - (.add sync-sinks d) |
272 |
| - (.add deferreds (async-send d msg dsts))) |
| 285 | + (let [^Downstream dwn (.next i)] |
| 286 | + (if (s/synchronous? (.sink dwn)) |
| 287 | + (.add sync-sinks dwn) |
| 288 | + (.add deferreds (async-send dwn msg dsts))) |
273 | 289 | (recur))))
|
274 | 290 |
|
275 | 291 | (loop []
|
|
284 | 300 | (recur)))))
|
285 | 301 |
|
286 | 302 | (loop []
|
287 |
| - (let [^Downstream d (.poll sync-sinks)] |
288 |
| - (if (nil? d) |
| 303 | + (let [^Downstream dwn (.poll sync-sinks)] |
| 304 | + (if (nil? dwn) |
289 | 305 | nil
|
290 | 306 | (do
|
291 |
| - (sync-send d msg dsts (when (.upstream? d) source)) |
| 307 | + (sync-send dwn msg dsts (when (.upstream? dwn) source)) |
292 | 308 | (recur)))))
|
293 | 309 |
|
294 | 310 | (recur))))
|
|
309 | 325 | downstream? true}
|
310 | 326 | :as opts}]
|
311 | 327 | (locking src
|
312 |
| - (let [d (Downstream. |
313 |
| - timeout |
314 |
| - (boolean (and upstream? (instance? IEventSink src))) |
315 |
| - downstream? |
316 |
| - dst |
317 |
| - description) |
| 328 | + (let [dwn (Downstream. |
| 329 | + timeout |
| 330 | + (boolean (and upstream? (instance? IEventSink src))) |
| 331 | + downstream? |
| 332 | + dst |
| 333 | + description) |
318 | 334 | k (.weakHandle ^IEventStream src ref-queue)]
|
319 | 335 | (if-let [dsts (.get handle->downstreams k)]
|
320 |
| - (.add ^CopyOnWriteArrayList dsts d) |
| 336 | + (.add ^CopyOnWriteArrayList dsts dwn) |
321 | 337 | (let [dsts (CopyOnWriteArrayList.)]
|
322 | 338 | (if-let [dsts' (.putIfAbsent handle->downstreams k dsts)]
|
323 |
| - (.add ^CopyOnWriteArrayList dsts' d) |
| 339 | + (.add ^CopyOnWriteArrayList dsts' dwn) |
324 | 340 | (do
|
325 |
| - (.add ^CopyOnWriteArrayList dsts d) |
| 341 | + (.add ^CopyOnWriteArrayList dsts dwn) |
326 | 342 | (if (s/synchronous? src)
|
327 | 343 | (sync-connect src dsts)
|
328 | 344 | (async-connect src dsts))))))))))
|
0 commit comments