clojure-dev

Issues: https://clojure.atlassian.net/browse/CLJ | Guide: https://insideclojure.org/2015/05/01/contributing-clojure/
2019-09-05T20:48:21.062500Z

Sorry if I sound like a broken record here -- new question from me but still have Java memory model correct synchronization of data between threads bouncing in my brain, and looked at the implementations of all of the transducers within Clojure. A bunch have no internal state, so look perfectly safe to move between threads, and a bunch more have a single item of internal state created and updated using volatile!, so also look safe to me.

2019-09-05T20:49:14.063600Z

partition-by and partition-all look unsafe to me, from what I know. They have not only a volatile! in their internal state, but also a java.util.ArrayList, whose Java API docs say require outside synchronization if you do add method calls on them, which those transducers do.

2019-09-05T20:49:40.064100Z

Those java.util.ArrayList objects are not synchronized in the code of partitional-all or partition-by.

alexmiller 2019-09-05T20:59:59.064600Z

there is a ticket for the partition ones

alexmiller 2019-09-05T21:00:30.064800Z

https://clojure.atlassian.net/browse/CLJ-2146

alexmiller 2019-09-05T21:01:09.065200Z

if you patch, I'd be happy to screen it, it's been vetted by rich already

2019-09-05T21:02:47.065700Z

Just went looking for an existing JIRA, and then noticed you already linked to it when I came back 🙂

2019-09-05T21:05:43.066600Z

Thinking about a patch -- quickly realizing that detecting that code might be improperly synchronized, and finding the most efficient correction, are different levels of difficulty.

alexmiller 2019-09-05T21:15:06.067Z

you can follow the path of other stateful transducers using volatile

alexmiller 2019-09-05T21:15:18.067300Z

I don't think it's any different than those

2019-09-05T21:34:02.069200Z

Yep, that is one way to skin that cat -- just will look a bit messy probably since there are a fair number of Java method calls for mutating it.

2019-09-05T21:34:22.069300Z

I am trying to work out if any of the current ways we have to use transducers (in core an core.async) would have an issue there, and I can't see that they would.

2019-09-05T21:35:16.070Z

in core things don't just change threads, and in core.async thread changes all happen around taking channel locks

alexmiller 2019-09-05T22:20:03.070200Z

That’s the idea

alexmiller 2019-09-05T22:20:29.070700Z

@andy.fingerhut not sure I understand what’s hard

2019-09-05T22:22:06.071700Z

nothing hard, I believe. Except I am finding sometimes, getting attachments onto JIRA tickets.

alexmiller 2019-09-05T22:28:52.072600Z

Yeah, make sure to turn off the “new” ui if you haven’t as it is bad

alexmiller 2019-09-05T22:29:59.074700Z

Given the optimizations around clearing young objects, I wonder if it would actually be better to use nil for empty partition and just throw it away when done rather than clearing and reusing

alexmiller 2019-09-05T22:30:26.075500Z

Would simplify the code a lot

alexmiller 2019-09-05T22:30:45.075900Z

And may even be faster

2019-09-05T22:31:54.076900Z

I can try a variant like that.

2019-09-05T22:32:40.078Z

clearing young objects, meaning generational GC? Or some other optimizations you are referring to there?

alexmiller 2019-09-05T22:32:46.078200Z

I’m in the car so can’t properly look at the patch but doing multiple ops on the volatile has safe publication but not thread safety, but I guess that doesn’t matter in this context

2019-09-05T22:34:39.079700Z

If by thread safety you mean that things can go badly if multiple threads simultaneously call this transducer function, then perfectly agreed, but good that none of the stateful transducers are intended to work in such an environment.

2019-09-05T23:00:03.080200Z

@hiredman I would be curious to learn what you find out there.