Skip to content
This repository was archived by the owner on Dec 12, 2022. It is now read-only.

Commit 1c10770

Browse files
committed
Implement segregated readable/writable component interfaces and processing
1 parent 46ed145 commit 1c10770

File tree

6 files changed

+285
-172
lines changed

6 files changed

+285
-172
lines changed

src/main/java/io/netty/buffer/api/Buf.java

Lines changed: 58 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,11 @@
1515
*/
1616
package io.netty.buffer.api;
1717

18+
import io.netty.buffer.api.ComponentProcessor.OfReadable;
19+
import io.netty.buffer.api.ComponentProcessor.OfWritable;
20+
import io.netty.buffer.api.ComponentProcessor.ReadableComponent;
21+
import io.netty.buffer.api.ComponentProcessor.WritableComponent;
22+
1823
import java.nio.ByteBuffer;
1924
import java.nio.ByteOrder;
2025

@@ -493,7 +498,7 @@ default void ensureWritable(int size) {
493498

494499
/**
495500
* Get the number of "components" in this buffer, that are readable. These are the components that would be
496-
* processed by {@link #forEachReadable(int, ComponentProcessor)}. For composite buffers, this is the number of
501+
* processed by {@link #forEachReadable(int, OfReadable)}. For composite buffers, this is the number of
497502
* transitive constituent buffers that are readable, while non-composite buffers only have at most one readable
498503
* component.
499504
* <p>
@@ -506,7 +511,7 @@ default void ensureWritable(int size) {
506511

507512
/**
508513
* Get the number of "components" in this buffer, that are writable. These are the components that would be
509-
* processed by {@link #forEachWritable(int, ComponentProcessor)}. For composite buffers, this is the number of
514+
* processed by {@link #forEachWritable(int, OfWritable)}. For composite buffers, this is the number of
510515
* transitive constituent buffers that are writable, while non-composite buffers only have at most one writable
511516
* component.
512517
* <p>
@@ -520,20 +525,20 @@ default void ensureWritable(int size) {
520525
/**
521526
* Process all readable components of this buffer, and return the number of components processed.
522527
* <p>
523-
* The given {@linkplain ComponentProcessor processor} is called for each component in this buffer, and passed a
524-
* component index, for the given component in the iteration, and a {@link Component} object for accessing the data
525-
* within the given component.
528+
* The given {@linkplain OfReadable processor} is called for each readable component in this buffer,
529+
* and passed a component index, for the given component in the iteration, and a {@link ReadableComponent} object
530+
* for accessing the data within the given component.
526531
* <p>
527-
* The component index is specific to the particular invokation of this method, and may change. The first call to
528-
* the consumer will be passed the given initial index, and the next call will be passed the initial index plus one,
529-
* and so on.
532+
* The component index is specific to the particular invokation of this method. The first call to the consumer will
533+
* be passed the given initial index, and the next call will be passed the initial index plus one, and so on.
530534
* <p>
531-
* The {@link ComponentProcessor} may stop the iteration at any time by returning {@code false}. This may cause the
532-
* number of components processed to be returned as a negative number (to signal early return), and the number of
533-
* components processed may then be less than the {@linkplain #countReadableComponents() readable component count}.
535+
* The {@linkplain OfReadable component processor} may stop the iteration at any time by returning {@code false}.
536+
* This will cause the number of components processed to be returned as a negative number (to signal early return),
537+
* and the number of components processed may then be less than the
538+
* {@linkplain #countReadableComponents() readable component count}.
534539
* <p>
535-
* <strong>Note</strong> that the {@link Component} instance passed to the consumer could be reused for multiple
536-
* calls, so the data must be extracted from the component in the context of the iteration.
540+
* <strong>Note</strong> that the {@link ReadableComponent} instance passed to the consumer could be reused for
541+
* multiple calls, so the data must be extracted from the component in the context of the iteration.
537542
* <p>
538543
* The {@link ByteBuffer} instances obtained from the component, share life time with that internal component.
539544
* This means they can be accessed as long as the internal memory store remain unchanged. Methods that may cause
@@ -549,14 +554,50 @@ default void ensureWritable(int size) {
549554
* this buffer instance.
550555
*
551556
* @param initialIndex The initial index of the iteration, and the index that will be passed to the first call to
552-
* the {@linkplain ComponentProcessor#process(int, Component) processor}.
557+
* the {@linkplain OfReadable#process(int, ReadableComponent) processor}.
553558
* @param processor The processor that will be used to process the buffer components.
554559
* @return The number of readable components processed, as a positive number of all readable components were
555560
* processed, or as a negative number if the iteration was stopped because
556-
* {@link ComponentProcessor#process(int, Component)} returned {@code false}.
561+
* {@link OfReadable#process(int, ReadableComponent)} returned {@code false}.
557562
* In any case, the number of components processed may be less than {@link #countComponents()}.
558563
*/
559-
int forEachReadable(int initialIndex, ComponentProcessor processor);
564+
int forEachReadable(int initialIndex, OfReadable processor);
560565

561-
int forEachWritable(int initialIndex, ComponentProcessor processor);
566+
/**
567+
* Process all writable components of this buffer, and return the number of components processed.
568+
* <p>
569+
* The given {@linkplain OfWritable processor} is called for each writable component in this buffer,
570+
* and passed a component index, for the given component in the iteration, and a {@link WritableComponent} object
571+
* for accessing the data within the given component.
572+
* <p>
573+
* The component index is specific to the particular invokation of this method. The first call to the consumer will
574+
* be passed the given initial index, and the next call will be passed the initial index plus one, and so on.
575+
* <p>
576+
* The {@link OfWritable component processor} may stop the iteration at any time by returning {@code false}.
577+
* This will cause the number of components processed to be returned as a negative number (to signal early return),
578+
* and the number of components processed may then be less than the
579+
* {@linkplain #countReadableComponents() readable component count}.
580+
* <p>
581+
* <strong>Note</strong> that the {@link WritableComponent} instance passed to the consumer could be reused for
582+
* multiple calls, so the data must be extracted from the component in the context of the iteration.
583+
* <p>
584+
* The {@link ByteBuffer} instances obtained from the component, share life time with that internal component.
585+
* This means they can be accessed as long as the internal memory store remain unchanged. Methods that may cause
586+
* such changes, are any method that requires the buffer to be {@linkplain #isOwned() owned}.
587+
* <p>
588+
* The best way to ensure this doesn't cause any trouble, is to use the buffers directly as part of the iteration,
589+
* or immediately after the iteration.
590+
* <p>
591+
* Changes to position and limit of the byte buffers exposed via the processed components, are not reflected back to
592+
* this buffer instance.
593+
*
594+
* @param initialIndex The initial index of the iteration, and the index that will be passed to the first call to
595+
* the {@linkplain OfWritable#process(int, WritableComponent) processor}.
596+
* @param processor The processor that will be used to process the buffer components.
597+
* @return The number of writable components processed, as a positive number of all writable components were
598+
* processed, or as a negative number if the iteration was stopped because
599+
* {@link OfWritable#process(int, WritableComponent)} returned {@code false}.
600+
* In any case, the number of components processed may be less than {@link #countComponents()}.
601+
*/
602+
int forEachWritable(int initialIndex, OfWritable processor);
562603
}

src/main/java/io/netty/buffer/api/Component.java

Lines changed: 0 additions & 71 deletions
This file was deleted.

src/main/java/io/netty/buffer/api/ComponentProcessor.java

Lines changed: 150 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,155 @@
1515
*/
1616
package io.netty.buffer.api;
1717

18-
@FunctionalInterface
18+
import java.nio.ByteBuffer;
19+
20+
/**
21+
* This interface contain a collection of APIs used in the {@link Buf#forEachReadable(int, OfReadable)} and
22+
* {@link Buf#forEachWritable(int, OfWritable)} methods.
23+
*/
1924
public interface ComponentProcessor {
20-
boolean process(int index, Component component);
25+
/**
26+
* A processor of {@linkplain ReadableComponent readable components}.
27+
*/
28+
@FunctionalInterface
29+
interface OfReadable extends ComponentProcessor {
30+
/**
31+
* Process the given component at the given index in the {@link Buf#forEachReadable(int, OfReadable) iteration}.
32+
* <p>
33+
* The component object itself is only valid during this call, but the {@link ByteBuffer byte buffers}, arrays,
34+
* and native address pointers obtained from it, will be valid until any
35+
* {@link Buf#isOwned() ownership} requiring operation is performed on the buffer.
36+
*
37+
* @param index The current index of the given buffer component, based on the initial index passed to the
38+
* {@link Buf#forEachReadable(int, OfReadable)} method.
39+
* @param component The current buffer component being processed.
40+
* @return {@code true} if the iteration should continue and more components should be processed, otherwise
41+
* {@code false} to stop the iteration early.
42+
*/
43+
boolean process(int index, ReadableComponent component);
44+
}
45+
46+
/**
47+
* A processor of {@linkplain WritableComponent writable components}.
48+
*/
49+
@FunctionalInterface
50+
interface OfWritable extends ComponentProcessor {
51+
/**
52+
* Process the given component at the given index in the
53+
* {@link Buf#forEachWritable(int, OfWritable)} iteration}.
54+
* <p>
55+
* The component object itself is only valid during this call, but the {@link ByteBuffer byte buffers}, arrays,
56+
* and native address pointers obtained from it, will be valid until any
57+
* {@link Buf#isOwned() ownership} requiring operation is performed on the buffer.
58+
*
59+
* @param index The current index of the given buffer component, based on the initial index passed to the
60+
* {@link Buf#forEachWritable(int, OfWritable)} method.
61+
* @param component The current buffer component being processed.
62+
* @return {@code true} if the iteration should continue and more components should be processed, otherwise
63+
* {@code false} to stop the iteration early.
64+
*/
65+
boolean process(int index, WritableComponent component);
66+
}
67+
68+
/**
69+
* A view onto the buffer component being processed in a given iteration of
70+
* {@link Buf#forEachReadable(int, OfReadable)}.
71+
*/
72+
interface ReadableComponent {
73+
74+
/**
75+
* Check if this component is backed by a cached byte array than can be accessed cheaply.
76+
* <p>
77+
* <strong>Note</strong> that regardless of what this method returns, the array should not be used to modify the
78+
* contents of this buffer component.
79+
*
80+
* @return {@code true} if {@link #readableArray()} is a cheap operation, otherwise {@code false}.
81+
*/
82+
boolean hasReadableArray();
83+
84+
/**
85+
* Get a byte array of the contents of this component.
86+
* <p>
87+
* <strong>Note</strong> that the array is meant to be read-only. It may either be a direct reference to the
88+
* concrete array instance that is backing this component, or it is a fresh copy.
89+
* Writing to the array may produce undefined behaviour.
90+
*
91+
* @return A byte array of the contents of this component.
92+
* @throws UnsupportedOperationException if {@link #hasReadableArray()} returns {@code false}.
93+
*/
94+
byte[] readableArray();
95+
96+
/**
97+
* An offset into the {@link #readableArray()} where this component starts.
98+
*
99+
* @return An offset into {@link #readableArray()}.
100+
* @throws UnsupportedOperationException if {@link #hasReadableArray()} returns {@code false}.
101+
*/
102+
int readableArrayOffset();
103+
104+
/**
105+
* Give the native memory address backing this buffer, or return 0 if this buffer has no native memory address.
106+
* <p>
107+
* <strong>Note</strong> that the address should not be used for writing to the buffer memory, and doing so may
108+
* produce undefined behaviour.
109+
*
110+
* @return The native memory address, if any, otherwise 0.
111+
*/
112+
long readableNativeAddress();
113+
114+
/**
115+
* Get a {@link ByteBuffer} instance for this memory component.
116+
* <p>
117+
* <strong>Note</strong> that the {@link ByteBuffer} is read-only, to prevent write accesses to the memory,
118+
* when the buffer component is obtained through {@link Buf#forEachReadable(int, OfReadable)}.
119+
*
120+
* @return A new {@link ByteBuffer} for this memory component.
121+
*/
122+
ByteBuffer readableBuffer();
123+
}
124+
125+
/**
126+
* A view onto the buffer component being processed in a given iteration of
127+
* {@link Buf#forEachWritable(int, OfWritable)}.
128+
*/
129+
interface WritableComponent {
130+
131+
/**
132+
* Check if this component is backed by a cached byte array than can be accessed cheaply.
133+
*
134+
* @return {@code true} if {@link #writableArray()} is a cheap operation, otherwise {@code false}.
135+
*/
136+
boolean hasWritableArray();
137+
138+
/**
139+
* Get a byte array of the contents of this component.
140+
*
141+
* @return A byte array of the contents of this component.
142+
* @throws UnsupportedOperationException if {@link #hasWritableArray()} returns {@code false}.
143+
*/
144+
byte[] writableArray();
145+
146+
/**
147+
* An offset into the {@link #writableArray()} where this component starts.
148+
*
149+
* @return An offset into {@link #writableArray()}.
150+
* @throws UnsupportedOperationException if {@link #hasWritableArray()} returns {@code false}.
151+
*/
152+
int writableArrayOffset();
153+
154+
/**
155+
* Give the native memory address backing this buffer, or return 0 if this buffer has no native memory address.
156+
*
157+
* @return The native memory address, if any, otherwise 0.
158+
*/
159+
long writableNativeAddress();
160+
161+
/**
162+
* Get a {@link ByteBuffer} instance for this memory component, which can be used for modifying the buffer
163+
* contents.
164+
*
165+
* @return A new {@link ByteBuffer} for this memory component.
166+
*/
167+
ByteBuffer writableBuffer();
168+
}
21169
}

src/main/java/io/netty/buffer/api/CompositeBuf.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -740,7 +740,7 @@ public int countWritableComponents() {
740740
}
741741

742742
@Override
743-
public int forEachReadable(int initialIndex, ComponentProcessor processor) {
743+
public int forEachReadable(int initialIndex, ComponentProcessor.OfReadable processor) {
744744
checkReadBounds(readerOffset(), Math.max(1, readableBytes()));
745745
int visited = 0;
746746
for (Buf buf : bufs) {
@@ -758,7 +758,7 @@ public int forEachReadable(int initialIndex, ComponentProcessor processor) {
758758
}
759759

760760
@Override
761-
public int forEachWritable(int initialIndex, ComponentProcessor processor) {
761+
public int forEachWritable(int initialIndex, ComponentProcessor.OfWritable processor) {
762762
checkWriteBounds(writerOffset(), Math.max(1, writableBytes()));
763763
int visited = 0;
764764
for (Buf buf : bufs) {

0 commit comments

Comments
 (0)