The (go (<! c)) will add a pending take! on the c channel. The go block will not proceed while waiting for the take to proceed. The (>!! c 42) will use that pending take and immediately fulfill it without checking the buffer (there is none).
I really can't explain this very well so I'd recommend watching some of the talks on core.async instead. All the topics are covered - https://vimeo.com/100518968 - https://www.youtube.com/watch?v=enwIIGzhahw - https://www.youtube.com/watch?v=096pIlA3GDo On Monday, May 20, 2019 at 3:18:17 PM UTC+2, Brian Beckman wrote: > > Thanks, Thomas. I shouldn't have included the quoted code about (<!! c) in > my question because it distracts from what I really want to know, and what > I want to know is all about how (go (<! c)) "makes buffer space available" > so that (>!! c 42) doesn't block. > > The following is an attempt to clarify my question. I first (go (<! c)) > and give the name d to the result, which is a channel that I am going > read-from later. Channel d is "connected to" or "relayed from" c. I then > (>!! c 42), and then (<!! d), both on the blocking "UI" thread. Everything > works. I wasted your attention by writing some code that would block (<!! > c) if it weren't quoted. > > Here is the part I don't understand: the documentation says that (>!! c > 42) will block "if there is no buffer space available," and the > documentation does not specify any other conditions. Well, I created c with > no buffer space, so, (>!! c 42) must block unless something else "makes > buffer space available," assuming the documentation is correct. The only > other interaction with c that could possibly be alive at the time when I do > (>!! c 42), is (go (<! c)), so (go (<! c)) must "make buffer space > available," assuming the documentation is correct. My understanding of (<! > c) (and I am suspicious of my understanding), is that (<! c) makes a > rendezvous available, not a buffer. If that understanding is correct, then > (>!! c 42) should block because there is no buffer available. > > On Sunday, May 19, 2019 at 1:48:16 PM UTC-7, Thomas Heller wrote: >> >> (<!! c) will hang because the value you put into c has already been taken >> by the first go (running in a different thread). So it is blocking until >> something puts another value into c. Since nothing ever does your program >> hangs. >> >> If it helps you can read "go" as "please run this somewhere else, >> possibly at a different time" and let the current thread continue after the >> go. >> >> I can't explain this very well but the documentation aspect is accurate. >> >> On Sunday, May 19, 2019 at 7:33:07 PM UTC+2, Brian Beckman wrote: >>> >>> The documentation for >!! reads: >>> >>> ------------------------- >>> clojure.core.async/>!! >>> ([port val]) >>> puts a val into port. nil values are not allowed. Will block if no >>> buffer space is available. Returns true unless port is already closed. >>> >>> >>> I have a case where I believe that the channel has no buffer, I park a >>> "pseudothread" in a go block reading off that channel via <!, and then >>> (lexically, not temporally), put to the unbuffered channel via >!!: >>> >>> (let [c (chan) ;; NO BUFFER! >>> d (go (<! c)) ;; park a pseudothread to read c >>> e (>!! c 42)] ;; blocking write to c, will unpark c's pseudothread >>> (println {:c-coughs-up '(this will hang (<!! c)), >>> :d-coughs-up (<!! d), >>> :what's-e e}) >>> (close! c) (close! d)) >>> >>> {:c-coughs-up (this will hang (<!! c)), :d-coughs-up 42, :what's-e true} >>> >>> >>> This case leads me to wonder whether the documentation might read >>> >>> >!! will block if there is no buffer space available *and* if there is >>> no *rendezvous *available, that is, no pseudothread parked waiting for >>> <!. >>> >>> but it's more likely that I completely misunderstand core.async because >>> I just made up the notion of a pseudothread in my struggle to understand! >>> >>> >>> >>> -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en --- You received this message because you are subscribed to the Google Groups "Clojure" group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/clojure/568ddcbe-2e3a-4e6b-a97e-c060e3b7fb37%40googlegroups.com. For more options, visit https://groups.google.com/d/optout.