Puts committed on take! when buffer is full and buffer contains an expanding transducer


This issue came up here: https://groups.google.com/d/topic/clojure/w_p4f3gNo3s/discussion
Another (possibly) related previous discussion: https://groups.google.com/d/topic/clojure-dev/9Ai-ZuCezOY/discussion

The scenario:
1. a channel has a fixed buffer of 1 and an expanding transducer `(mapcat identity)`
2. a single put! is performed with a collection (C1)
3. a blocking take! is initiated in another thread
4. a second put! is performed with another collection

I expected any put!'s to fail until all elements of collection C1 are taken from the channel.

Non-blocking put!'s (via offer!) do fail until then.

Blocking put!'s do block – but only until a single take! is executed on the channel. That's surprising. Where does the put!'s value go? Everything does continue to "work" as expected, but the buffer acts like it has grown to size 2 (2 input collections, 1 partially output via the transducer)

I believe this is resolved by checking whether the buffer is full during a take! after the call to `(impl/remove! buffer)` but before processing any puts. See the patch for exactly what I mean. I'm not sure whether this change breaks anything as I'm not too familiar with this codebase; though tests do pass.


macOS 10.12.6
clojure 1.7.0 with core.async 0.3.466-SNAPSHOT (rev 0498ba69fda5d930e3e7568cc90ca933c19c42ca)


macOS 10.12.6
clojure 1.9.0 with core.async 0.3.465


Alex Miller
January 10, 2020, 6:48 PM

Released in 0.7.559

Brian J. Rubinton
January 10, 2020, 5:44 PM

Thanks, Alex!

Alex Miller
January 10, 2020, 5:30 PM

Patch applied

Brian J. Rubinton
January 7, 2018, 5:17 PM

Replaced the patch with one including a test demonstrating the behavior with the change and without.

Your pinned fields
Click on the next to a field label to start pinning.




Brian J. Rubinton