go

added

ns
clojure.core.async

type
macro

(go & body)

Asynchronously executes the body, returning immediately to the
calling thread. Additionally, any visible calls to <!, >! and alt!/alts!
channel operations within the body will block (if necessary) by
'parking' the calling thread rather than tying up an OS thread (or
the only JS thread when in ClojureScript). Upon completion of the
operation, the body will be resumed.

Returns a channel which will receive the result of the body when
completed

                user=> (doseq [n (range 10)
               :let [i (-> n
                           inc
                           range
                           rand-nth)]]                    
         (go
           (<! (timeout (* i 1000)))
           (println n)))
nil
5
3
0
6
4
7
1
2
9
8


            
                (require '[clojure.core.async :as async])

; create channel
(def c (async/chan))

; create promise
(def d (promise))

; record high-res timestamp;
; place value (1) on channel;
; in a callback, record duration of time between enqueueing and dequeueing;
; resolve promise with that value
(let [t (. System (nanoTime))]
 (async/put! c 1
  (fn [_]
   (deliver d (- (. System (nanoTime)) t)))))

; do a blocking take from the channel, do a blocking resolve of the promise
(println "taken value, delivery time" [(async/<!! c) @d])

; same as above but with go block
(def tc
 (let [t (. System (nanoTime))]
  (async/put! c 2)
  (async/go [(async/<! c) (- (. System (nanoTime)) t)])))

; go blocks return a channel immediately, 
; the actual return value of the go block gets placed on the channel when ready
(println "taken value, delivery time" (async/<!! tc))

;; taken value, delivery time [1 1191935]
;; taken value, delivery time [2 1668001]