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

Description

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.

Environment

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

and

macOS 10.12.6
clojure 1.9.0 with core.async 0.3.465

Assignee

Unassigned

Reporter

Brian J. Rubinton

Labels

None

Approval

None

Patch

Code

Priority

Major
Configure