Sadly, put! on a closed channel has never thrown an exception (regardless
of what the docstring says).

I'll list the semantics, but note that the wording gets a bit clumsy due to
the way threading works. So if I say "if the channel is closed when the
put! occurs", the "occurs" is at the time that the lock happens internally
to the channel. So it's possible to call put! and then close the channel
before the call to put returns. I assume that this behavior makes sense to
most.

Semantics are thus:

Definition of terms:

put succeeded - the channel was not closed, and the put found a pending take
put enqueued - the channel was not closed, and no takers were found.

--------
With this patch:

>!, >!! now returns true if the put succeeded. A falsey value is returned
if the put was discarded due to the channel being closed.

(put! c val) returns true if the put was enqueued or succeeded.

(put! c val callback) callback is called with true if the put succeeded.
The callback is called with falsey if the value was discarded due to the
channel being closed.

The part that trips some people up is that the value returned by the put is
both returned and handed to the callback, so there are two ways to get the
value.

----------

So to answer your question about closing with pending puts.

1) call put! on an open channel with no takes.
2) put! returns true, since the put was enqueued. But since it was
enqueued, the callback has not been dispatched.
3) close! the channel. Still no dispatch as close! does not discard data
4) call take!. The take will succeed instantly (due to the pending put),
and the callback will be dispatched with true since the put succeeded.

Therefore, the value given the callback is less about the status of the
channel, and more about if the value has been given to a taker.

One more example:

1) call put! on a closed channel
2) put returns falsey
3) the callback is dispatched with falsey


Hopefully this helps.

Timothy


On Thu, Jan 23, 2014 at 2:28 PM, Sean Corfield <s...@corfield.org> wrote:

> Can you confirm:
>
> * Today, calling put! on a closed channel throws an exception (according
> to its docstring).
> * After this change, calling put! on a closed channel will return nil
> instead.
>
> The current docstring says that the function will be called "when
> complete" which I took to mean when the value is actually placed in the
> channel (i.e., no longer pending) so I'm confused by your comment about
> pending puts... What happens if a put is enqueued on an open channel and
> then it is closed before the put is "complete"? It seems like put! would
> return true and the function would simply not be called?
>
> Just trying to make sure I understand this properly.
>
> I think it's a good change (even tho' it breaks any code that uses put!
> and expects it to throw an exception).
>
> Sean
>
> On Jan 23, 2014, at 6:05 AM, Timothy Baldridge <tbaldri...@gmail.com>
> wrote:
> > I'm looking for some feedback on recent changes Rich and I have made to
> core.async:
> >
> > I merged the "put ret" branch into master of core.async. This commit
> introduces some changes to the core.async API that provides feedback during
> a put! operation.
> >
> > The changes to the public api are fairly simple:
> >
> > (let [result (put! c 42 (fn [result] nil))]
> >   nil)
> >
> > In this snippet, both result variables (in the callback and in the
> return value) will return true, unless the channel is already closed. Since
> this value is propagated to >! as well, termination of writers is now
> fairly easy:
> >
> > (loop [x 0]
> >   (when (>! c x)
> >     (recur (inc x))))
> >
> > Note: these new semantics don't change how pending puts are handled when
> a channel closes. So if a put! returns true, the callback will not later be
> called with false if the channel is closed. Once a put operation is
> enqueued it will stay enqueued until a taker removes the operation. Close!
> will still not remove pending puts.
> >
> > WARNING!!! The inclusion of these changes means we have to break the
> public API. The function handed to put! now takes one argument instead of
> zero arguments. This will instantly break any code that uses put!.
> Therefore when upgrading to 0.1.0-SNAPSHOT you will need to update all
> calls to put!. I'm sorry about this, but there's really no other way to get
> these changes into the api.
> >
> > Please let me know about any bugs you find in the current 0.1.0-SNAPSHOT.
>
>


-- 
"One of the main causes of the fall of the Roman Empire was that-lacking
zero-they had no way to indicate successful termination of their C
programs."
(Robert Firth)

-- 
-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
"Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.

Reply via email to