alts!

added

ns
clojure.core.async

type
function

(alts! ports & {:as opts})

Completes at most one of several channel operations. Must be called
inside a (go ...) block. ports is a vector of channel endpoints,
which can be either a channel to take from or a vector of
[channel-to-put-to val-to-put], in any combination. Takes will be
made as if by <!, and puts will be made as if by >!. Unless
the :priority option is true, if more than one port operation is
ready a non-deterministic choice will be made. If no operation is
ready and a :default value is supplied, [default-val :default] will
be returned, otherwise alts! will park until the first operation to
become ready completes. Returns [val port] of the completed
operation, where val is the value taken for takes, and a
boolean (true unless already closed, as per put!) for puts.

opts are passed as :key val ... Supported options:

:default val - the value to use if none of the operations are immediately ready
:priority true - (default nil) when true, the operations will be tried in order.

Note: there is no guarantee that the port exps or val exprs will be
used, nor in what order should they be, so they should not be
depended upon for side effects.

                user> (let [chans (partition-all 2
                                 (interleave
                                  ["Bob"
                                   "Jane"
                                   "GuyGirl22"]
                                  (repeatedly 3 chan)))]
        (go
          (let [[owner port] (rand-nth chans)
                chans-only (mapv second chans)]

            (go
              (<! (timeout 1500))
              (>! port
                  (str owner ": First!!!")))

            (let [[v p] (alts! chans-only)]
              (println "Message: " v "\
From Object: " p)))))

;; Returns => #<ManyToManyChannel clojure.core.async.impl.channels.ManyToManyChannel@446ab69a>

;; 1.5 seconds later =>
;; Message:  Bob: First!!! 
;; From Object:  #<ManyToManyChannel clojure.core.async.impl.channels.ManyToManyChannel@15ac28ae>

            
                ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; THIS example shows `:default`s and `:priority`s

(let [f (fn [x ch] (go (Thread/sleep (rand 100))
                                (>! ch x)))
      a (chan)
      b (chan)
      c (chan)]
  (println "----------")
  (f 1 a)
  (f 2 b)
  (f 3 c)
  (Thread/sleep 200) ; if this is commented out, it returns the
                     ; `:default` every time. If the thread *does*
                     ; sleep, then it returns the `a` channel's `1`
                     ; every time
  (let [[n ch2] (alts!! [a b c]
                        :default 42
                        :priority true
                        )]
    (println "received: " n)))