Commit Graph

11 Commits

Author SHA1 Message Date
Chris Vest
ef714c90d9 Hide Rc.countBorrows
The state that people really care about is whether or not an Rc has ownership.
Exposing the reference count will probably just confuse people.
The reference count is still exposed on RcSupport because it may be (and is, in the case of ByteBufAdaptor) needed to support implementation details.
2021-05-07 11:25:42 +02:00
Chris Vest
0ccb34ca08 Fix failing ByteBufAdaptorTests and increase adaptor compatibility 2021-03-16 12:11:29 +01:00
Chris Vest
253b6cb919 Allow slices to obtain ownership when parent is closed
Motivation:
It is kind of a weird internal and hidden state, that slices were special.
For instance, slices could not be sent, and they could never obtain ownership.
This means buffers from slices behaved differently from allocated buffers.
In doing so, they violated both the principle that magic should stay hidden, and the principle of consistent behaviour.

Modification:
- The special reference-counting drop implementation that was added to support bifurcation, has been renamed to ArcDrop (for atomic reference counting).
- The ArcDrop is then used throughout the MemSegBuffer implementation to account for every instance where multiple buffers reference the same memory, e.g. slices and the like.
- Borrows of a buffer is then the sum of borrows from the buffer itself, and its ArcDrop.
- Ownership is thus tied to both the buffer itself being owned, and the ArcDrop being in an owned state.
- SizeClassedMemoryPool is changed to pool recoverable memory instead of sends, because the sends could come from slices.
- We also take care to keep around a "base" memory segment, so that we don't return memory segment slices to the memory pool (doing so would leak the memory from the parent segment that is not part of the slice).
- CleanerPooledDrop now keeps a weak reference to itself, rather than the buffer, which is more correct anyway, but now also required because we cannot rely on the buffer reference the cleaner was created with.
- The CleanerPooledDrop now takes care to drop the buffer that is actually passed to it, rather than what it was referencing from some earlier point.
- MemoryManager can now disclose the size of recoverable memory, so that SizeClassedMemoryPool can pick the correct size pool to return memory to. It cannot rely on the passed down buffer instance for this, because that buffer might have been a slice.

Result:
It is now possible for slices to obtain ownership when their parent buffer is closed.
2021-03-15 16:42:56 +01:00
Chris Vest
0867f99be1 Add LifecycleTracer to help debug lifecycle/ownership issues
Motivation:
With reference counting it can be difficult to keep track of ownership and references.
When bugs arise in this area, it's good to get help from some tooling.

Modification:
Add a LifecycleTracer which records lifecycle changes.
This information can be attached to any lifecycle/ownership exceptions as suppressed exceptions.
The tracing is off by default, unless assertions are enabled.

Result:
It's now easier to debug reference counting/lifecycle/ownership issues.
2021-03-05 16:32:10 +01:00
Chris Vest
1b65bf9a23 Make the incubating buffers exposable as ByteBuf
Motivation:
This makes it possible to use the new buffer API in Netty as is.

Modification:
Make the MemSegBuffer implementation class implement AsByteBuf and ReferenceCounted.
The produced ByteBuf instance delegates all calls to the underlying Buffer instance as faithfully as possible.
One area where the two deviates, is that it's not possible to create non-retained duplicates and slices with the new buffer API.

Result:
It is now possible to use the new buffer API on both client and server side.
The Echo* examples demonstrate this, and the EchoIT proves it with a test.
The API is used more directly on the client side, since the server-side allocator in Netty does not know how to allocate buffers with the incubating API.
2021-03-01 10:49:09 +01:00
Chris Vest
492977d9be Introduce Deref abstraction
Motivation:
Sometimes, we wish to operate on both buffers and anything that can produce a buffer.
For instance, when making a composite buffer, we could compose either buffers or sends.

Modification:
Introduce a Deref interface, which is extended by both Rc and Send.
A Deref can be used to acquire an Rc instance, and in doing so will also acquire a reference to the Rc.
That is, dereferencing increases the reference count.
For Rc itself, this just delegates to Rc.acquire, while for Send it delegates to Send.receive, and can only be called once.
The Allocator.compose method has been changed to take Derefs.
This allows us to compose either Bufs or Sends of bufs.
Or a mix.
Extra care and caution has been added to the code, to make sure the reference counts are managed correctly when composing buffers, now that it's a more complicated operation.
A handful of convenience methods for working with Sends have also been added to the Send interface.

Result:
We can now build a composite buffer out of sends of buffers.
2021-02-11 14:26:57 +01:00
Chris Vest
02eb4286fa Better method names and javadocs in RcSupport 2020-12-11 12:09:32 +01:00
Chris Vest
bb2264ac5b Address review comments on bifurcate PR 2020-12-10 12:51:18 +01:00
Chris Vest
b749106c0c Add a Buf.bifurcate method
Motivation:
There are use cases that involve accumulating data into a buffer, then carving out prefix slices and sending them off on their own journey for further processing.

Modification:
Add a Buf.bifurcate API, that split a buffer, and its ownership, in two.
Internally, the API will inject and maintain an atomically reference counted Drop instance, so that the original memory segment is not released until all bifurcated parts are closed.
This works particularly well for composite buffers, where only the buffer (if any) wherein the bifurcation point lands, will actually have its memory split. A composite buffer can otherwise just crack its buffer array in two.

Result:
We now have a safe way of breaking the single ownership of some memory into multiple parts, that can be sent and owned independently.
2020-12-10 10:29:31 +01:00
Chris Vest
a1785e8161 Move the MemorySegment based Buf implementation to its own package, and break the remaining bits of tight coupling. 2020-11-17 15:53:40 +01:00
Chris Vest
3efa93841e Rename the 'b2' package to 'api' 2020-11-17 15:40:13 +01:00