Slide 1

Slide 1 text

Yet another introduction to core.async Takahrio Noda (@tnoda) 2014-11-15 Sat

Slide 2

Slide 2 text

Outline Queue Blocking/Non-blocking Secret Alien Technology

Slide 3

Slide 3 text

Producers and consumers p1 c1 c2 c3 c4 c5 p2 p3 p4 p5

Slide 4

Slide 4 text

Queue p1 Queue p2 p3 p4 p5 c1 c2 c3 c4 c5

Slide 5

Slide 5 text

java.util.concurrent.LinkedBlockingQueue .put LinkedBlockingQueue .take Example (Clojure) user> (import ’java.util.concurrent.LinkedBlockingQueue) java.util.concurrent.LinkedBlockingQueue user> (def q (LinkedBlockingQueue.)) #’user/q

Slide 6

Slide 6 text

.put/.take Example (Clojure) user> (.put q 1) nil user> (.put q "foo") nil user> (.take q) 1 user> (.take q) "foo"

Slide 7

Slide 7 text

clojure.core.async/chan put! chan take! Example (require) user> (require ’[clojure.core.async :refer [chan put! take!] :as async]) nil user> (def c (chan)) #’user/c

Slide 8

Slide 8 text

put!/take! (1/2) Example (put! and take!) user> (put! c 1) true user> (put! c 2) true user> (take! c println) 1 nil user> (take! c println) 2 nil

Slide 9

Slide 9 text

put!/take! (2/2) Example (Asynchronous) user> (take! c #(println "Got first:" %)) nil user> (take! c #(println "Got second:" %)) nil user> (put! c 11) true user> (put! c 12) true *nrepl-server* ; ; ; ; ; ; ; Got first: 11 ; ; Got second: 12

Slide 10

Slide 10 text

close! (1/2) put! X chan take! Example (require) user> (require ’[clojure.core.async :refer [chan put! take! close!] :as async]) nil user> (def c (chan)) #’user/c

Slide 11

Slide 11 text

close! (2/2) Example (close!) user> (put! c 1) true user> (close! c) nil user> (put! c 2) false user> (take! c println) 1 nil user> (take! c println) nil nil

Slide 12

Slide 12 text

Overflow Example (Pending puts) user> (def c (chan)) #’user/c user> (dorun (repeatedly #(put! c 42))) AssertionError Assert failed: No more than 1024 pending puts are allowed on a single channel. Consider using a windowed buffer. (< (.size puts) impl/MAX-QUEUE-SIZE) clojure.core.async.impl.channels.ManyToManyChannel (channels.clj:150)

Slide 13

Slide 13 text

dropping-buffer Example (dropping-buffer) user> (require ’[clojure.core.async :refer [chan put! take! close! dropping-buffer] :as async]) nil user> (def c (chan (dropping-buffer 3))) #’user/c user> (dotimes [n 10000] (put! c n)) nil user> (dotimes [_ 3] (take! c #(print % "| "))) 0 | 1 | 2 | nil

Slide 14

Slide 14 text

sliding-buffer Example (sliding-buffer) user> (require ’[clojure.core.async :refer [chan put! take! close! sliding-buffer] :as async]) nil user> (def c (chan (sliding-buffer 3))) #’user/c user> (dotimes [n 10000] (put! c n)) nil user> (dotimes [_ 3] (take! c #(print % "| "))) 9997 | 9998 | 9999 | nil

Slide 15

Slide 15 text

default chan Example (default chan) user> (require ’[clojure.core.async :refer [chan put! take! close!] :as async]) nil user> (def c (chan)) #’user/c user> (dotimes [n 1024] (put! c n)) nil user> (put! c 1024) AssertionError Assert failed: ...

Slide 16

Slide 16 text

fixed-size buffer (size == 0) Example (buffer) user> (require ’[clojure.core.async :refer [chan put! take! close! buffer] :as async]) nil user> (def c (chan (buffer 0))) #’user/c user> (dotimes [n 1024] (put! c n)) nil user> (put! c 1024) AssertionError Assert failed: ...

Slide 17

Slide 17 text

fixed-size buffer (size == 10) Example (buffer) user> (def c (chan (buffer 10))) #’user/c user> (dotimes [n 1024] (put! c n)) nil user> (dotimes [n 1024] (put! c n (println n))) 0 1 2 . . . 10 AssertionError Assert failed: ...

Slide 18

Slide 18 text

Parking puts put! take! Parking (up to 1024) Buffer Channel

Slide 19

Slide 19 text

Checkpoint 1 chan puts! take! close! buffer No more than 1024 pending puts are allowed on a single channel. dropping-buffer sliding-buffer buffer default (size == 0)

Slide 20

Slide 20 text

Return value LinkedBlockingQueue .put LinkedBlockingQueue .take value chan put! chan take! nil

Slide 21

Slide 21 text

>!! and (put! c 1) true user> (put! c 2) true user> ( ( (>!! c 3) ; will be blocked

Slide 22

Slide 22 text

Return values nil (callback) put! / take! Value >!! /

Slide 23

Slide 23 text

Thread Example (future) user> (def f #(-> (apply *’ (range 1 100000)) (rem 1000000009))) #’user/f user> (def c (chan)) #’user/c user> (future (>!! c (f))) # user> (

Slide 24

Slide 24 text

thread Example (thread) user> (

Slide 25

Slide 25 text

timeout Example (Thread/sleep and future) user> (def c (let [ch (chan)] (future (Thread/sleep 3000) (close! ch)) ch)) #’user/c user> ( (

Slide 26

Slide 26 text

Checkpoint 2 Blocking/Non-blocking Blocking Return value put!, take! No nil (callback) >!!,

Slide 27

Slide 27 text

Promise >!! promise >!! promise

Slide 28

Slide 28 text

Secret Alien Technology >! ??? >! ???

Slide 29

Slide 29 text

go go block (go ; do >! or (def f #(-> (apply *’ (range 1 100000)) (rem 1000000009))) #’user/f user> (go (f)) # (

Slide 30

Slide 30 text

10k go-blocks demo

Slide 31

Slide 31 text

Go blocks Example (Quil) (def c (chan (sliding-buffer 10000))) (defn -main [& args] (dotimes [x size] (dotimes [y size] (go-loop [] (>! c [x y (rand-int 255)]) (

Slide 32

Slide 32 text

go/go-loop Example (go + loop) (go (loop [x a y b] ; do something (recur c d))) Example (go-loop) (go-loop [x a y b] ; do something (recur c d))

Slide 33

Slide 33 text

Go blocks (recap) Example (Quil) (def c (chan (sliding-buffer 10000))) (defn -main [& args] (dotimes [x size] (dotimes [y size] (go-loop [] (>! c [x y (rand-int 255)]) (

Slide 34

Slide 34 text

alt!! Channels c1

Slide 35

Slide 35 text

alt! alt! c1 alt! c2 alt!! c1 alt!! c2

Slide 36

Slide 36 text

Checkpoint 3 Go blocks go, go-loop >!,

Slide 37

Slide 37 text

core.async Channel chan, thread, timeout, go Blocking, Non-blocking >!!, !,