Skip to content

Commit 93c0137

Browse files
Ryland Degnanrobertroeser
Ryland Degnan
authored andcommitted
Replace IntObjectHashMap with NonBlockingHashMapLong (#459)
1 parent 9bd625f commit 93c0137

File tree

11 files changed

+2972
-64
lines changed

11 files changed

+2972
-64
lines changed

Diff for: build.gradle

+3-3
Original file line numberDiff line numberDiff line change
@@ -80,8 +80,8 @@ subprojects {
8080
}
8181

8282
dependencies {
83-
compile "io.projectreactor:reactor-core:3.1.1.RELEASE"
84-
compile "io.netty:netty-buffer:4.1.16.Final"
83+
compile "io.projectreactor:reactor-core:3.1.2.RELEASE"
84+
compile "io.netty:netty-buffer:4.1.17.Final"
8585
compile "org.reactivestreams:reactive-streams:1.0.1"
8686
compile "org.slf4j:slf4j-api:1.7.25"
8787
compile "com.google.code.findbugs:jsr305:3.0.2"
@@ -90,7 +90,7 @@ subprojects {
9090
testCompile "org.mockito:mockito-core:2.10.0"
9191
testCompile "org.hamcrest:hamcrest-library:1.3"
9292
testCompile "org.slf4j:slf4j-log4j12:1.7.25"
93-
testCompile "io.projectreactor:reactor-test:3.1.1.RELEASE"
93+
testCompile "io.projectreactor:reactor-test:3.1.2.RELEASE"
9494
}
9595

9696
publishing {

Diff for: rsocket-core/src/main/java/io/rsocket/Frame.java

+1
Original file line numberDiff line numberDiff line change
@@ -500,6 +500,7 @@ public static int initialRequestN(final Frame frame) {
500500
result = 1;
501501
break;
502502
case FIRE_AND_FORGET:
503+
case METADATA_PUSH:
503504
result = 0;
504505
break;
505506
default:

Diff for: rsocket-core/src/main/java/io/rsocket/RSocketClient.java

+27-26
Original file line numberDiff line numberDiff line change
@@ -16,41 +16,36 @@
1616

1717
package io.rsocket;
1818

19-
import static io.rsocket.util.ExceptionUtil.noStacktrace;
20-
2119
import io.netty.buffer.Unpooled;
22-
import io.netty.util.collection.IntObjectHashMap;
2320
import io.rsocket.exceptions.ConnectionException;
2421
import io.rsocket.exceptions.Exceptions;
2522
import io.rsocket.internal.LimitableRequestPublisher;
2623
import io.rsocket.internal.UnboundedProcessor;
27-
import java.nio.channels.ClosedChannelException;
24+
import io.rsocket.util.NonBlockingHashMapLong;
25+
import org.reactivestreams.Publisher;
26+
import org.reactivestreams.Subscriber;
27+
import reactor.core.Disposable;
28+
import reactor.core.publisher.*;
29+
30+
import javax.annotation.Nullable;
2831
import java.time.Duration;
2932
import java.util.Collection;
3033
import java.util.concurrent.atomic.AtomicBoolean;
3134
import java.util.concurrent.atomic.AtomicInteger;
3235
import java.util.function.Consumer;
3336
import java.util.function.Function;
3437
import java.util.function.Supplier;
35-
import javax.annotation.Nullable;
36-
import org.reactivestreams.Publisher;
37-
import org.reactivestreams.Subscriber;
38-
import reactor.core.Disposable;
39-
import reactor.core.publisher.*;
4038

4139
/** Client Side of a RSocket socket. Sends {@link Frame}s to a {@link RSocketServer} */
4240
class RSocketClient implements RSocket {
4341

44-
private static final ClosedChannelException CLOSED_CHANNEL_EXCEPTION =
45-
noStacktrace(new ClosedChannelException());
46-
4742
private final DuplexConnection connection;
4843
private final Function<Frame, ? extends Payload> frameDecoder;
4944
private final Consumer<Throwable> errorConsumer;
5045
private final StreamIdSupplier streamIdSupplier;
5146
private final MonoProcessor<Void> started;
52-
private final IntObjectHashMap<LimitableRequestPublisher> senders;
53-
private final IntObjectHashMap<Subscriber<Payload>> receivers;
47+
private final NonBlockingHashMapLong<LimitableRequestPublisher> senders;
48+
private final NonBlockingHashMapLong<UnicastProcessor<Payload>> receivers;
5449
private final AtomicInteger missedAckCounter;
5550

5651
private final UnboundedProcessor<Frame> sendProcessor;
@@ -80,8 +75,8 @@ class RSocketClient implements RSocket {
8075
this.errorConsumer = errorConsumer;
8176
this.streamIdSupplier = streamIdSupplier;
8277
this.started = MonoProcessor.create();
83-
this.senders = new IntObjectHashMap<>(256, 0.9f);
84-
this.receivers = new IntObjectHashMap<>(256, 0.9f);
78+
this.senders = new NonBlockingHashMapLong<>(256);
79+
this.receivers = new NonBlockingHashMapLong<>(256);
8580
this.missedAckCounter = new AtomicInteger();
8681

8782
// DO NOT Change the order here. The Send processor must be subscribed to before receiving
@@ -127,7 +122,7 @@ class RSocketClient implements RSocket {
127122
}
128123

129124
private void handleSendProcessorError(Throwable t) {
130-
Collection<Subscriber<Payload>> values;
125+
Collection<UnicastProcessor<Payload>> values;
131126
Collection<LimitableRequestPublisher> values1;
132127
synchronized (RSocketClient.this) {
133128
values = receivers.values();
@@ -151,7 +146,7 @@ private void handleSendProcessorCancel(SignalType t) {
151146
if (SignalType.ON_ERROR == t) {
152147
return;
153148
}
154-
Collection<Subscriber<Payload>> values;
149+
Collection<UnicastProcessor<Payload>> values;
155150
Collection<LimitableRequestPublisher> values1;
156151
synchronized (RSocketClient.this) {
157152
values = receivers.values();
@@ -222,10 +217,15 @@ public Flux<Payload> requestChannel(Publisher<Payload> payloads) {
222217

223218
@Override
224219
public Mono<Void> metadataPush(Payload payload) {
225-
final Frame requestFrame = Frame.Request.from(0, FrameType.METADATA_PUSH, payload, 1);
226-
payload.release();
227-
sendProcessor.onNext(requestFrame);
228-
return Mono.empty();
220+
Mono<Void> defer =
221+
Mono.fromRunnable(
222+
() -> {
223+
final Frame requestFrame = Frame.Request.from(0, FrameType.METADATA_PUSH, payload, 1);
224+
payload.release();
225+
sendProcessor.onNext(requestFrame);
226+
});
227+
228+
return started.then(defer);
229229
}
230230

231231
@Override
@@ -303,7 +303,7 @@ private Mono<Payload> handleRequestResponse(final Payload payload) {
303303
Frame.Request.from(streamId, FrameType.REQUEST_RESPONSE, payload, 1);
304304
payload.release();
305305

306-
MonoProcessor<Payload> receiver = MonoProcessor.create();
306+
UnicastProcessor<Payload> receiver = UnicastProcessor.create();
307307

308308
synchronized (this) {
309309
receivers.put(streamId, receiver);
@@ -312,6 +312,7 @@ private Mono<Payload> handleRequestResponse(final Payload payload) {
312312
sendProcessor.onNext(requestFrame);
313313

314314
return receiver
315+
.singleOrEmpty()
315316
.doOnError(t -> sendProcessor.onNext(Frame.Error.from(streamId, t)))
316317
.doOnCancel(() -> sendProcessor.onNext(Frame.Cancel.from(streamId)))
317318
.doFinally(
@@ -438,7 +439,7 @@ private boolean contains(int streamId) {
438439

439440
protected void cleanup() {
440441
try {
441-
Collection<Subscriber<Payload>> subscribers;
442+
Collection<UnicastProcessor<Payload>> subscribers;
442443
Collection<LimitableRequestPublisher> publishers;
443444
synchronized (RSocketClient.this) {
444445
subscribers = receivers.values();
@@ -468,9 +469,9 @@ private synchronized void cleanUpLimitableRequestPublisher(
468469
}
469470
}
470471

471-
private synchronized void cleanUpSubscriber(Subscriber<?> subscriber) {
472+
private synchronized void cleanUpSubscriber(UnicastProcessor<?> subscriber) {
472473
try {
473-
subscriber.onError(CLOSED_CHANNEL_EXCEPTION);
474+
subscriber.cancel();
474475
} catch (Throwable t) {
475476
errorConsumer.accept(t);
476477
}

Diff for: rsocket-core/src/main/java/io/rsocket/RSocketServer.java

+14-13
Original file line numberDiff line numberDiff line change
@@ -16,20 +16,12 @@
1616

1717
package io.rsocket;
1818

19-
import static io.rsocket.Frame.Request.initialRequestN;
20-
import static io.rsocket.frame.FrameHeaderFlyweight.FLAGS_C;
21-
import static io.rsocket.frame.FrameHeaderFlyweight.FLAGS_M;
22-
2319
import io.netty.buffer.ByteBuf;
2420
import io.netty.buffer.Unpooled;
25-
import io.netty.util.collection.IntObjectHashMap;
2621
import io.rsocket.exceptions.ApplicationException;
2722
import io.rsocket.internal.LimitableRequestPublisher;
2823
import io.rsocket.internal.UnboundedProcessor;
29-
import java.util.Collection;
30-
import java.util.function.Consumer;
31-
import java.util.function.Function;
32-
import javax.annotation.Nullable;
24+
import io.rsocket.util.NonBlockingHashMapLong;
3325
import org.reactivestreams.Publisher;
3426
import org.reactivestreams.Subscriber;
3527
import org.reactivestreams.Subscription;
@@ -39,6 +31,15 @@
3931
import reactor.core.publisher.SignalType;
4032
import reactor.core.publisher.UnicastProcessor;
4133

34+
import javax.annotation.Nullable;
35+
import java.util.Collection;
36+
import java.util.function.Consumer;
37+
import java.util.function.Function;
38+
39+
import static io.rsocket.Frame.Request.initialRequestN;
40+
import static io.rsocket.frame.FrameHeaderFlyweight.FLAGS_C;
41+
import static io.rsocket.frame.FrameHeaderFlyweight.FLAGS_M;
42+
4243
/** Server side RSocket. Receives {@link Frame}s from a {@link RSocketClient} */
4344
class RSocketServer implements RSocket {
4445

@@ -47,8 +48,8 @@ class RSocketServer implements RSocket {
4748
private final Function<Frame, ? extends Payload> frameDecoder;
4849
private final Consumer<Throwable> errorConsumer;
4950

50-
private final IntObjectHashMap<Subscription> sendingSubscriptions;
51-
private final IntObjectHashMap<UnicastProcessor<Payload>> channelProcessors;
51+
private final NonBlockingHashMapLong<Subscription> sendingSubscriptions;
52+
private final NonBlockingHashMapLong<UnicastProcessor<Payload>> channelProcessors;
5253

5354
private final UnboundedProcessor<Frame> sendProcessor;
5455
private Disposable receiveDisposable;
@@ -62,8 +63,8 @@ class RSocketServer implements RSocket {
6263
this.requestHandler = requestHandler;
6364
this.frameDecoder = frameDecoder;
6465
this.errorConsumer = errorConsumer;
65-
this.sendingSubscriptions = new IntObjectHashMap<>();
66-
this.channelProcessors = new IntObjectHashMap<>();
66+
this.sendingSubscriptions = new NonBlockingHashMapLong<>();
67+
this.channelProcessors = new NonBlockingHashMapLong<>();
6768

6869
// DO NOT Change the order here. The Send processor must be subscribed to before receiving
6970
// connections

0 commit comments

Comments
 (0)