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