This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2018-01-15
Channels
- # adventofcode (6)
- # beginners (63)
- # boot (39)
- # cider (25)
- # clara (9)
- # cljs-dev (27)
- # clojure (100)
- # clojure-dev (39)
- # clojure-dusseldorf (7)
- # clojure-italy (32)
- # clojure-russia (23)
- # clojure-spec (28)
- # clojure-uk (51)
- # clojurescript (197)
- # core-async (44)
- # cursive (3)
- # datomic (14)
- # emacs (4)
- # fulcro (27)
- # graphql (23)
- # hoplon (4)
- # jobs (9)
- # juxt (1)
- # leiningen (3)
- # nyc (1)
- # off-topic (6)
- # om (7)
- # onyx (6)
- # parinfer (11)
- # re-frame (23)
- # reagent (15)
- # ring-swagger (1)
- # rum (15)
- # shadow-cljs (37)
- # sql (24)
- # uncomplicate (4)
- # unrepl (17)
inside a go block, what is the difference between putting onto another channel via put!
vs >!
. i've always used put
even from inside go blocks
put! has no backpressure - it returns immediately and leaves your go block running
while >! will pause that block until the value is consumed or buffered, which means you have backpressure
both are async - when you pause the go block you are pausing a state machine and it resumes later
but yeah - it’s kind of like that
but it’s an important distinciton in cljs for example, that both are properly async
i suppose put! is fine unless for some reason I need to access the value from another channel within the same go block?
put! works for simple things, as your design evolves having backpressure will prevent a lot of problems
I would only use put! inside a go block if I need to consume from the same channel I just sent to, later in the same block
@ajs in the jvm, there’s only a small number of threads to run go blocks on, and it’s easy to get them congested
in cljs it’s even worse - only one thread shared by both core.async and all other code
when you use put! you don’t cause the context switch that lets other code (eg. the code that needs that value) to run
so in cljs put! can cause deadlocks that >! would not cause
(at least in theory)
you said, >! will pause that block until the value is consumed or buffered -- doesn't that mean the execution will possibly continue after this put even if it is not actually consumed and dealt with (in the case it is bufferred), in which case if you depend on it being consumed it would be no different than a put!
?
the distinction is that put! doesn’t introduce a context switch
which means that the other code isn’t given a chance to run
so if your go block is doing something, and it depends on some other go block or take operation happening before your go block is done, you'd want >!
or if you need any other go block or non go block code to run, period, you need to eventually call <!, >!, or exit
i guess i don't understand the context switch you are talking about, or why i'd care when putting onto a channel if it is consumed right away
another aspect here is that put! is not part of the CSP model
it doesn’t get consumed if you never let the context switch
(unless you count “being buffered for use” as consumption)
your code works because eventually you either exit or use <! - but if you started using take! as well for example, you could easily lock up your app
js is cooperative multitasking - there’s nothing inside your code (except eg. setTimeout?) that can interrupt your code mid execution
<! and >! are yields in the coroutine model, they inform the go system that other code is free to run
with coroutines, it’s good policy to yield whenever it makes sense to
outside a go block, the only way to put onto a channel asynchronously is with put!
if you don't want to block, so perhaps i just got into that habit and therefore did that in go blocks too
that’s a reasonable explanation. But I’d default to >! in go blocks unless there’s a pressing reason not to
same reason: it needs to be async because there’s no preemption so your code blocks for ever, nothing can create the condition that would allow it to continue
so in short, recommended to put! outside a go block, >! instead inside a go block, and always take with <! in a go block
when you have one thread and no preemption, waiting on a condition is equivalent to a deadlock
here's another theoretical. in js, what if any performance difference would you find between sending things around to say 10 different channels, which are read from in 10 go blocks, vs. (if your logic allowed for this), having a "heterogeneous" single channel that would accept 10 different responsibilities and handle different types of message content accordingly
I wonder - sounds like an interesting thing to try measuring