[concurrency-interest] draft Carrier API

Alex Otenko oleksandr.otenko at gmail.com
Sun Mar 8 22:31:48 UTC 2020

Naming things is maybe the hardest problem in computer science :) but in
the end people are going to get used to the convention, whatever you choose.

But the type of receive() is going to affect how the code is structured. So
I would suggest to spend some time understanding the implications.

Was: blocking queue, can be shown to be a co-list. (take() is the
destructor removing head)

Now: blocking queue with an end, so it becomes a representation of a list
(possibly finite). At type level it becomes a union of co-list and a unit.
The disjoined unit is a special value returned (eg -1 returned by input
stream read), or a mutually exclusive continuation (onNext delivers head vs
onComplete delivers unit; fold gets a case for empty list and a function
for the case when the list has a head). So it's inevitable the special
value emerges in the API. Null, a special exception, empty Optional are
probably all you can do in Java.

I'd think Optional is the best choice. Null is not safe. Exceptions require
quite a bit of boilerplate, which can be annoying, especially given that it
doesn't reflect an error state.


On Sun, 8 Mar 2020, 16:36 Alex Otenko, <oleksandr.otenko at gmail.com> wrote:

> I am familiar with half closed states, but in the socket world. The use of
> the same term is lost on me.
> In networking, half closed socket is really a fully closed pipe in a
> duplex. Here it is more of half closed singular pipe - closing one end of
> the same pipe,  just from different ends. So some of the states that become
> possible are really strange.
> Calling it finish is better, but perhaps some confusion about possibly
> interpreting it as an imperative instruction is still there. (Telling the
> sender to "Finish!")
> My understanding that the intention is to capture Carrier transitioning
> like so:
> sending and receiving -> sending complete, receiver can only drain
> buffered items, reject future send attempts
> Or
> sending and receiving->receiving complete, no more items can be delivered,
> discard all buffered items and reject future send attempts, reject future
> attempts to receive
> Is that right?
> In the first case receiver needs some hint how many receives are sensible,
> and if a receive is blocked on empty when sender transitions into the
> sending done state, the receiver needs a nice way out. Throwing seems like
> last resort, as typically exceptions indicate transitioning into error
> states. Returning Optional<T> can be better.
> Alex
> On Sun, 8 Mar 2020, 13:37 Doug Lea, <dl at cs.oswego.edu> wrote:
>> On 3/8/20 8:49 AM, Alex Otenko via Concurrency-interest wrote:
>> > I think it may be useful to clarify who is meant to call each of the
>> > close methods.
>> Right; thanks especially for the questions about what confused
>> programmers who aren't used to dealing with half-closed states might do.
>>  Probably best to stop using "close" except for full close. And kill
>> closeForReceiving. Leaving better names and simpler specs:
>> interface Carriable<T> extends AutoCloseable {
>>     boolean isClosed();
>>     boolean isFinishedSending();    // closed or sending disabled
>>     //...
>> }
>> interface CarrierSender<T> extends Carriable<T> {
>>     void finishSending();           // disable sending; close when empty
>>     // ...
>> }
>> Full versions as usual at:
>> http://gee.cs.oswego.edu/dl/wwwtmp/Carrier.java

More information about the loom-dev mailing list