Fork me on GitHub

Hi, is future a lightweight thread similar to go blocks?


"lightweight thread" is a kind of terrible term


I am not sure I would call go blocks lightweight threads either


When a go block is running it is a normal jvm (native) thread


But when "blocked" on a channel it yields the thread. But the amount of data the go block hangs on to can easily dwarf the amount of data needed for thread bookkeeping. So what even is lightweight?


I kind of what you are trying to say.


So, a go block is just description of work, and a thread might pick it up and do a bit of it till time slice runs out or it hits a blocking call. Is that correct?


There is no time slice for go blocks, they are effectively cooperatively scheduled


(the native thread it is running on of course can be preempted, but the go block has no idea of that happens and it doesn't cause it to yield the thread to other go blocks)


So, when does the go block yield? Is it ONLY when it hits a parking call?


Yes, only on the special channel operations


That clears it. So, go blocks in a way mandate the use of channels.


Blocking io, taking locks, burning cpu without doing channel ops will all blockup the thread pool where go blocks run


I thought is was more general purpose. Thanks for the clarification.


The go macro is also a statically scoped transformation. So it only rewrites it's immediate body.


You are referring to the concept where a go block stops at the function boundary? I read the official guide but did not understand it fully.


it will not work if you move <! into a function, it has to be in the go block


I was a bit confused by that too. As a beginner, reading some of the documentation can be hard to unpick


What does it mean that it stops at the function boundary?

Alex Miller (Clojure team)16:12:52

The parking functions only work in a go macro because the go macro rewrites the code around it. So once you call into a function the go macro can no longer “see” it to do any rewriting


So, if I have something like this (go (if (pos? x) (anotherns/my-function x))), then what execution context will my-function have? In the sense of threads? On the same thread as the go-block, or elsewhere?


The same as the go block, and if my-function does any blocking operations it will clog up the threadpool


understood about blocking, I'm trying to understand better, It's just that I'm trying to consoldate this "once you call into a function, the go macro...", with what happens when I call into a function, and how threads etc. are maintained/created


function boundary means if there's a fn form between go and a parking form, it's not considered to be part of it


so e.g in the following form (go (fn [] (<! c))) the <! will not be rewritten, and thus is illegal


isn't <! async? why would it be parking?


parking operations are resolved at compile-time. if there's a function boundary between a parking operation and a go block, you can't know in advance the evaluation context, so the go macro just ignores it


Looks like I'll have to do more reading into the subject. Thank you! 🙂