WebSocket client API

Chris Hegarty chris.hegarty at oracle.com
Tue Oct 13 20:02:04 UTC 2015


Pavel,

> On 13 Oct 2015, at 10:40, Pavel Rappo <pavel.rappo at oracle.com> wrote:
> 
> Hi Simone,
> 
>> On 8 Oct 2015, at 20:51, Simone Bordet <simone.bordet at gmail.com> wrote:
>> 
>> The *API* should provide a callback to notify when the ByteBuffer has
>> been consumed.
> 
> Here is a proposed mechanism for managing buffers used by Listener.

I think that this is quite good. There is clearly a need for the receiving
callbacks, onXXX methods, to allocate ( since they pass the payload
as a ByteBuffer ), so exposing, through a small surface area, an API
that gives better control over this allocation ( for the 0.1%that may
want to do this ), without impacting on the 99.9% that couldn’t
care less about it, seems reasonable. It is a nice side-effect that 
pinning / explicit release can be built on top of this, albeit with a
small amount of work.

-Chris.



> 1. WebSocket.Builder gets 2 new methods (may not be an actual javadoc):
> 
>    /**
>     * Specifies a function that provides {@code ByteBuffer}s for {@code
>     * WebSocket} to receive Binary, Ping and Pong messages' payload to.
>     *
>     * <p> The function is called by {@code WebSocket} with a number of
>     * bytes should remain in the required buffer. This serves as a hint
>     * from the implementation to a user.
>     *
>     * @param provider the providing function
>     * @return this builder
>     */
>    public Builder byteBuffersForListener(IntFunction<? extends ByteBuffer> provider);
> 
>    /**
>     * Specifies a function that provides {@code CharBuffer}s for {@code
>     * WebSocket} to receive Text and Close messages' payload to.
>     *
>     * <p> The function is called by {@code WebSocket} with a number of
>     * chars should remain in the required buffer. This serves as a hint
>     * from the implementation to a user.
>     *
>     * @param provider the providing function
>     * @return this builder
>     */
>    public Builder charBuffersForListener(IntFunction<? extends CharBuffer> provider);
> 
> 2. If a user wants to use their own strategy of allocation/reuse they are fully
> in charge of this. For example:
> 
>    IntFunction<? extends CharBuffer> provider = (r) -> {
>        CharBuffer charBuffer = pool.getWithRemaining(r);
>        if (charBuffer == null)
>            charBuffer = CharBuffer.allocate(r);
>        return charBuffer;
>    };
> 
>    ...
>    builder.charBuffersForListener(provider) ... .buildAsync();
>    ...
> 
>    Later in the listener far, far away:
> 
>    @Override
>    public void onText(CharBuffer payload, boolean isLast) {
>        // ...
>        ws.sendText(payload, isLast).thenRun(() -> pool.recycle(payload));
>    }
> 
> Since the user constructs both the listener and the provider, they surely may now
> of each other, so the 'pool' can be easily captured by the listener.
> 
> 3. On the other hand we could specify a set of predefined providers, and default
> behaviour like:
> 
>    * one off provider: constructs buffers on demand for one time use
>    * reusing provider: always returns a buffer to the implementation at the
>      end of the onXXX invocation
> 
> In both cases above the user doesn't have to know about some additional
> recycle-handlers. Hence there's no need for onXXX methods to change their
> signatures to accommodate for it.
> 
> What would you think about it?
> 
> -Pavel
> 



More information about the net-dev mailing list