clojure-dev

Issues: https://clojure.atlassian.net/browse/CLJ | Guide: https://insideclojure.org/2015/05/01/contributing-clojure/
2019-09-04T21:25:46.044600Z

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)

alexmiller 2019-09-04T21:27:42.044900Z

channels have a mutex

alexmiller 2019-09-04T21:28:45.045600Z

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

alexmiller 2019-09-04T21:28:55.045900Z

when woken from a park

2019-09-04T21:29:53.046500Z

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

alexmiller 2019-09-04T21:30:20.046700Z

yes

alexmiller 2019-09-04T21:30:38.047200Z

that's the whole idea

2019-09-04T21:30:57.047900Z

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

alexmiller 2019-09-04T21:31:11.048300Z

where would "local data" be?

2019-09-04T21:31:37.048900Z

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

alexmiller 2019-09-04T21:31:55.049200Z

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

2019-09-04T21:32:43.049900Z

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

alexmiller 2019-09-04T21:33:24.050400Z

I think those are saved in an atom

alexmiller 2019-09-04T21:33:41.050900Z

stretching the limit of my memory

2019-09-04T21:33:47.051100Z

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.

alexmiller 2019-09-04T21:34:10.051600Z

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

2019-09-04T21:34:16.051800Z

thanks for the info

2019-09-04T21:37:00.052Z

its an atomic array

2019-09-04T21:37:40.052700Z

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)

2019-09-04T21:39:19.054200Z

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

2019-09-04T21:39:21.054400Z

yeah

2019-09-04T21:40:04.055700Z

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

2019-09-04T21:40:41.056500Z

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)

2019-09-04T21:42:42.057700Z

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

2019-09-04T21:44:11.059100Z

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

2019-09-04T21:45:18.060300Z

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.