@@ -45,10 +45,10 @@ public class ProtocolizedBuiltPacketImpl implements ProtocolizedBuiltPacket {
4545
4646 private final IntFunction <Packet > packetFactory ;
4747 private final int [] protocols ;
48- private final IntObjectMap <byte []> dataMap = new IntObjectHashMap <>( 2 ) ;
48+ private volatile IntObjectMap <byte []> dataMap ;
4949 private final boolean lazy ;
5050
51- public < T > ProtocolizedBuiltPacketImpl (final @ NotNull Packet packet , final boolean lazy , final int ... protocols ) {
51+ public ProtocolizedBuiltPacketImpl (final @ NotNull Packet packet , final boolean lazy , final int ... protocols ) {
5252 this (u -> packet , lazy , protocols );
5353 Objects .requireNonNull (packet , "packet must not be null" );
5454 }
@@ -78,32 +78,49 @@ public ProtocolizedBuiltPacketImpl(final @NotNull IntFunction<Packet> packetFact
7878 if (protocols .length == 0 ) {
7979 throw new IllegalArgumentException ("Protocols must not be empty. Use BuiltPacket instead if the packet is not protocolized." );
8080 }
81+ final IntObjectMap <byte []> initialMap = new IntObjectHashMap <>(lazy ? 2 : protocols .length );
8182 if (!lazy ) {
8283 for (final int protocol : protocols ) {
83- this .compute (protocol );
84+ final byte [] data = this .computeBytes (protocol );
85+ initialMap .put (protocol , data );
8486 }
8587 }
88+ this .dataMap = initialMap ;
8689 }
8790
8891 @ Override
8992 public ByteBuf get (final @ NotNull ByteBufAllocator allocator , final int protocol ) {
90- byte [] data = this .dataMap .get (protocol );
93+ IntObjectMap <byte []> localMap = this .dataMap ;
94+ byte [] data = localMap .get (protocol );
9195 if (data == null ) {
92- if (this .lazy && this .isAvailable (protocol )) {
93- data = this .compute (protocol , protocol , allocator );
94- } else {
95- final int low = this .findLow (protocol );
96- data = this .dataMap .get (low );
96+ synchronized (this ) {
97+ localMap = this .dataMap ;
98+ data = localMap .get (protocol );
9799 if (data == null ) {
98- data = this .compute (low , protocol , allocator );
99- this .dataMap .put (low , data );
100- } else {
101- this .dataMap .put (protocol , data );
100+ final IntObjectMap <byte []> newMap = copyOf (localMap );
101+
102+ if (this .lazy && this .isAvailable (protocol )) {
103+ data = this .computeBytes (protocol , allocator );
104+ newMap .put (protocol , data );
105+ } else {
106+ final int low = this .findLow (protocol );
107+ final byte [] lowData = localMap .get (low );
108+ if (lowData == null ) {
109+ data = this .computeBytes (low , allocator );
110+ newMap .put (low , data );
111+ newMap .put (protocol , data );
112+ } else {
113+ data = lowData ;
114+ newMap .put (protocol , data );
115+ }
116+ }
117+
118+ this .dataMap = newMap ;
102119 }
103120 }
104121 }
105- final int length = data . length ;
106- final ByteBuf buf = allocator .buffer (length , length );
122+
123+ final ByteBuf buf = allocator .buffer (data . length , data . length );
107124 buf .writeBytes (data );
108125 return buf ;
109126 }
@@ -118,17 +135,13 @@ private int findLow(final int protocol) {
118135 return nearLow ;
119136 }
120137
121- private byte [] compute (final int protocol ) {
122- return this .compute (protocol , protocol );
123- }
124-
125138 @ VisibleForTesting
126- byte [] compute (final int protocol , final int updateProtocol ) {
127- return this .compute (protocol , updateProtocol , ByteBufAllocator .DEFAULT );
139+ byte [] computeBytes (final int protocol ) {
140+ return this .computeBytes (protocol , ByteBufAllocator .DEFAULT );
128141 }
129142
130143 @ VisibleForTesting
131- byte [] compute (final int protocol , final int updateProtocol , final @ NotNull ByteBufAllocator allocator ) {
144+ byte [] computeBytes (final int protocol , final @ NotNull ByteBufAllocator allocator ) {
132145 final Packet packet = this .packetFactory .apply (protocol );
133146
134147 final ByteBuf buf = allocator .buffer ();
@@ -138,7 +151,7 @@ byte[] compute(final int protocol, final int updateProtocol, final @NotNull Byte
138151
139152 final byte [] data = new byte [buf .readableBytes ()];
140153 buf .getBytes (buf .readerIndex (), data );
141- this . dataMap . put ( updateProtocol , data );
154+
142155 return data ;
143156 } finally {
144157 buf .release ();
@@ -154,4 +167,12 @@ private boolean isAvailable(final int protocol) {
154167 return false ;
155168 }
156169
170+ private static IntObjectMap <byte []> copyOf (final IntObjectMap <byte []> source ) {
171+ final IntObjectMap <byte []> copy = new IntObjectHashMap <>(source .size () + 1 );
172+ for (final IntObjectMap .PrimitiveEntry <byte []> entry : source .entries ()) {
173+ copy .put (entry .key (), entry .value ());
174+ }
175+ return copy ;
176+ }
177+
157178}
0 commit comments