55import io .netty .util .collection .IntObjectMap ;
66import io .rsocket .DuplexConnection ;
77import io .rsocket .RSocket ;
8+ import io .rsocket .exceptions .CanceledException ;
89import io .rsocket .frame .decoder .PayloadDecoder ;
910import io .rsocket .plugins .RequestInterceptor ;
1011import java .util .Objects ;
1112import java .util .function .Function ;
13+ import reactor .core .publisher .Sinks ;
1214import reactor .util .annotation .Nullable ;
1315
1416class RequesterResponderSupport {
@@ -19,19 +21,24 @@ class RequesterResponderSupport {
1921 private final PayloadDecoder payloadDecoder ;
2022 private final ByteBufAllocator allocator ;
2123 private final DuplexConnection connection ;
24+ private final Sinks .Empty <Void > onGracefulShutdownSink ;
2225 @ Nullable private final RequestInterceptor requestInterceptor ;
2326
2427 @ Nullable final StreamIdSupplier streamIdSupplier ;
2528 final IntObjectMap <FrameHandler > activeStreams ;
2629
30+ boolean terminating ;
31+ boolean terminated ;
32+
2733 public RequesterResponderSupport (
2834 int mtu ,
2935 int maxFrameLength ,
3036 int maxInboundPayloadSize ,
3137 PayloadDecoder payloadDecoder ,
3238 DuplexConnection connection ,
3339 @ Nullable StreamIdSupplier streamIdSupplier ,
34- Function <RSocket , ? extends RequestInterceptor > requestInterceptorFunction ) {
40+ Function <RSocket , ? extends RequestInterceptor > requestInterceptorFunction ,
41+ Sinks .Empty <Void > onGracefulShutdownSink ) {
3542
3643 this .activeStreams = new IntObjectHashMap <>();
3744 this .mtu = mtu ;
@@ -41,6 +48,7 @@ public RequesterResponderSupport(
4148 this .allocator = connection .alloc ();
4249 this .streamIdSupplier = streamIdSupplier ;
4350 this .connection = connection ;
51+ this .onGracefulShutdownSink = onGracefulShutdownSink ;
4452 this .requestInterceptor = requestInterceptorFunction .apply ((RSocket ) this );
4553 }
4654
@@ -88,6 +96,9 @@ public int getNextStreamId() {
8896 final StreamIdSupplier streamIdSupplier = this .streamIdSupplier ;
8997 if (streamIdSupplier != null ) {
9098 synchronized (this ) {
99+ if (this .terminating ) {
100+ throw new CanceledException ("Disposed" );
101+ }
91102 return streamIdSupplier .nextStreamId (this .activeStreams );
92103 }
93104 } else {
@@ -107,6 +118,10 @@ public int addAndGetNextStreamId(FrameHandler frameHandler) {
107118 if (streamIdSupplier != null ) {
108119 final IntObjectMap <FrameHandler > activeStreams = this .activeStreams ;
109120 synchronized (this ) {
121+ if (this .terminating ) {
122+ throw new CanceledException ("Disposed" );
123+ }
124+
110125 final int streamId = streamIdSupplier .nextStreamId (activeStreams );
111126
112127 activeStreams .put (streamId , frameHandler );
@@ -119,6 +134,11 @@ public int addAndGetNextStreamId(FrameHandler frameHandler) {
119134 }
120135
121136 public synchronized boolean add (int streamId , FrameHandler frameHandler ) {
137+ if (this .terminating ) {
138+ throw new CanceledException (
139+ "This RSocket is either disposed or disposing, and no longer accepting new requests" );
140+ }
141+
122142 final IntObjectMap <FrameHandler > activeStreams = this .activeStreams ;
123143 // copy of Map.putIfAbsent(key, value) without `streamId` boxing
124144 final FrameHandler previousHandler = activeStreams .get (streamId );
@@ -148,14 +168,45 @@ public synchronized FrameHandler get(int streamId) {
148168 * @return {@code true} if there is {@link FrameHandler} for the given {@code streamId} and the
149169 * instance equals to the passed one
150170 */
151- public synchronized boolean remove (int streamId , FrameHandler frameHandler ) {
152- final IntObjectMap <FrameHandler > activeStreams = this .activeStreams ;
153- // copy of Map.remove(key, value) without `streamId` boxing
154- final FrameHandler curValue = activeStreams .get (streamId );
155- if (!Objects .equals (curValue , frameHandler )) {
156- return false ;
171+ public boolean remove (int streamId , FrameHandler frameHandler ) {
172+ final boolean terminated ;
173+ synchronized (this ) {
174+ final IntObjectMap <FrameHandler > activeStreams = this .activeStreams ;
175+ // copy of Map.remove(key, value) without `streamId` boxing
176+ final FrameHandler curValue = activeStreams .get (streamId );
177+ if (!Objects .equals (curValue , frameHandler )) {
178+ return false ;
179+ }
180+ activeStreams .remove (streamId );
181+ if (this .terminating && activeStreams .size () == 0 ) {
182+ terminated = true ;
183+ this .terminated = true ;
184+ } else {
185+ terminated = false ;
186+ }
187+ }
188+
189+ if (terminated ) {
190+ onGracefulShutdownSink .tryEmitEmpty ();
157191 }
158- activeStreams .remove (streamId );
159192 return true ;
160193 }
194+
195+ public void terminate () {
196+ final boolean terminated ;
197+ synchronized (this ) {
198+ this .terminating = true ;
199+
200+ if (activeStreams .size () == 0 ) {
201+ terminated = true ;
202+ this .terminated = true ;
203+ } else {
204+ terminated = false ;
205+ }
206+ }
207+
208+ if (terminated ) {
209+ onGracefulShutdownSink .tryEmitEmpty ();
210+ }
211+ }
161212}
0 commit comments