/
walkthrough.clj
87 lines (55 loc) · 2.11 KB
/
walkthrough.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
;; This walkthrough introduces the core concepts of conquerant.
;; It is inspired by and roughly mimics the core.async walkthrough.
(require '[conquerant.core :as c])
;;;; Promises
;; Execution is synchronized by waiting on promises,
;; which are instances of `java.util.concurrent.CompletableFuture`.
;; Use `c/promise` to make an empty promise:
(c/promise)
;; Use `c/complete` to deliver a promise:
(c/complete (c/promise) :done)
;;;; Blocking Reads
;; In ordinary threads, use `deref` or `@` to read the value in a promise:
(let [p (c/promise)]
(c/complete p "hello")
(assert (= "hello" @p)))
;; If we try to deref an unfulfilled promise, we will block the main thread.
;;;; Async / Await
;; The `c/async` macro asynchronously executes its body on a special pool
;; of threads. Reads that normally block will pause execution instead.
;; This mechanism encapsulates the inversion of control that is external
;; in event/callback systems.
;; Inside `c/async` blocks, we use `c/await` instead of `deref`.
;; Here we convert our prior example to use async/await:
(let [p (c/promise)]
(c/async (let [v (c/await p)]
(assert (= "hello" v))))
(c/complete p "hello"))
;; `c/promise`s can be delivered from inside:
(let [p (c/promise [resolve]
(resolve "hello"))]
(c/async (let [v (c/await p)]
(assert (= "hello" v)))))
;; `c/async` also returns a promise:
(let [p (c/async "hello")]
(c/async (let [v (c/await p)]
(assert (= "hello" v)))))
;;;; Timeouts
;; `c/await` can timeout like deref:
(c/async (let [p (c/promise)
v (c/await p 1000 :not-done)]
(assert (= :not-done v))))
;;;; Custom Threadpools
;; conquerant supports switching the threadpool
;; on which async blocks and promises run:
(letfn [(info [id]
(locking *out*
(println id "running on thread:"
(.getName (Thread/currentThread)))))]
(c/async (info "async 1"))
(c/promise [_]
(info "promise 1"))
(c/with-async-executor (java.util.concurrent.ForkJoinPool. 1)
(c/async (info "async 2"))
(c/promise [_]
(info "promise 2"))))