Fork me on GitHub
#clojure-dev
<
2019-09-04
>
andy.fingerhut21:09:46

In the Clojure/Java implementation of core.async, what kind of Java synchronization techniques, if any, are used when a go block switches from running in one thread T1, to running in a different thread T2? (feel free to correct any misimpressions that may be revealed in the question itself)

alexmiller21:09:42

channels have a mutex

alexmiller21:09:45

go blocks become suspended computations (ie functions) that are invoked

alexmiller21:09:55

when woken from a park

andy.fingerhut21:09:53

Can a go block be parked after running in thread T1, then later woken and run in thread T2?

alexmiller21:09:38

that's the whole idea

andy.fingerhut21:09:57

and any "local data" in the go block will not necessarily have gone through any synchronization mechanisms, unless the Clojure developer adds them?

alexmiller21:09:11

where would "local data" be?

andy.fingerhut21:09:37

loop/let symbols, fn. parameters, ...

alexmiller21:09:55

it'll be run in the context of restored local bindings etc

andy.fingerhut21:09:43

saved and restored local bindings, with or without Java synchronization mechanisms provided by the core.async implementation machinery?

alexmiller21:09:24

I think those are saved in an atom

alexmiller21:09:41

stretching the limit of my memory

andy.fingerhut21:09:47

I can look this up myself in the code, if it isn't on the tip of your brain -- not trying to get you to do any extensive time digging here.

alexmiller21:09:10

that's about as far as I remember, have to run anyhow

andy.fingerhut21:09:16

thanks for the info

hiredman21:09:00

its an atomic array

hiredman21:09:40

bindings created with binding are also saved and restored as the go block moves between threads (I think there are some outstanding issues with that though)

hiredman21:09:19

where locals would be saved in to the, uh, stackframe I guess on the jvm they instead get stored into the atomic array

hiredman21:09:04

and the array has a few extra slots for other bits of dynamic information, bindings, exception handlers

andy.fingerhut21:09:41

So if a go block has mutable data that it modifies, and doesn't explicitly try to synchronize it, the act of core.async writing references to such mutable data into an AtomicReferenceArray in thread T1, then reading it back out when restoring in thread T2, should synchronize all of those changes made by T1 and make them visible in T2. (statement, not question -- but corrections welcome)

hiredman21:09:42

I vaguely get the sense that is the idea, but I don't know enough to evaluate if that goal is successful achieved

hiredman21:09:11

I think I have seen tickets where people have argued you could use a regular array in the go implementation, relying on the channel locks for visibility

andy.fingerhut21:09:18

Sounds like a bit more "global" property of the implementation, and thus a bit harder to check, and easier to break, but it does seem at least possible in principle.