Pavel, > On 13 Oct 2015, at 10:40, Pavel Rappo <pavel.ra...@oracle.com> wrote: > > Hi Simone, > >> On 8 Oct 2015, at 20:51, Simone Bordet <simone.bor...@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 >