Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@
import io.grpc.internal.StatsTraceContext;
import java.util.concurrent.Executor;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.atomic.AtomicInteger;

import javax.annotation.Nullable;
import javax.annotation.concurrent.ThreadSafe;

Expand All @@ -73,7 +73,12 @@ public final class BinderClientTransport extends BinderTransport
private final Bindable serviceBinding;

/** Number of ongoing calls which keep this transport "in-use". */
private final AtomicInteger numInUseStreams;
@GuardedBy("this")
private int numInUseStreams;

/** Last in-use state that was reported to the listener */
@GuardedBy("this")
private boolean listenerInUse;

private final long readyTimeoutMillis;
private final PingTracker pingTracker;
Expand Down Expand Up @@ -114,7 +119,8 @@ public BinderClientTransport(
Boolean preAuthServerOverride = options.getEagAttributes().get(PRE_AUTH_SERVER_OVERRIDE);
this.preAuthorizeServer =
preAuthServerOverride != null ? preAuthServerOverride : factory.preAuthorizeServers;
numInUseStreams = new AtomicInteger();
numInUseStreams = 0;
listenerInUse = false;
pingTracker = new PingTracker(Ticker.systemTicker(), (id) -> sendPing(id));

serviceBinding =
Expand Down Expand Up @@ -259,9 +265,7 @@ public synchronized ClientStream newStream(
return newFailingClientStream(failure, attributes, headers, tracers);
}

if (inbound.countsForInUse() && numInUseStreams.getAndIncrement() == 0) {
clientTransportListener.transportInUse(true);
}
updateInUseStreamsIfNeed(inbound.countsForInUse(), 1);
Outbound.ClientOutbound outbound =
new Outbound.ClientOutbound(this, callId, method, headers, statsTraceContext);
if (method.getType().clientSendsOneMessage()) {
Expand All @@ -273,9 +277,7 @@ public synchronized ClientStream newStream(

@Override
protected void unregisterInbound(Inbound<?> inbound) {
if (inbound.countsForInUse() && numInUseStreams.decrementAndGet() == 0) {
clientTransportListener.transportInUse(false);
}
updateInUseStreamsIfNeed(inbound.countsForInUse(), -1);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please see "A note on synchronization" at the top of BinderTransport.java. Note that unregisterInbound() is called from Inbound.java's synchronized closeAbnormal() and deliverSuffix() methods (via unregister()) Is your proposed lock acquisition order safe or does it risk deadlock?

super.unregisterInbound(inbound);
}

Expand Down Expand Up @@ -305,7 +307,9 @@ void notifyShutdown(Status status) {
@Override
@GuardedBy("this")
void notifyTerminated() {
if (numInUseStreams.getAndSet(0) > 0) {
if(numInUseStreams > 0) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please format this code according to the style guide: https://google.github.io/styleguide/javaguide.html I recommend the https://github.com/google/google-java-format tool

numInUseStreams = 0;
listenerInUse = false;
clientTransportListener.transportInUse(false);
}
if (readyTimeoutFuture != null) {
Expand Down Expand Up @@ -391,6 +395,25 @@ private synchronized void handleAuthResult(Throwable t) {
Status.INTERNAL.withDescription("Could not evaluate SecurityPolicy").withCause(t), true);
}

/** Updates in-use-stream count and notifies listener only on transitions between 0 and >0 */
private synchronized void updateInUseStreamsIfNeed(boolean countsForInUse, int delta) {
if(!countsForInUse) {
return;
}

numInUseStreams += delta;
if(numInUseStreams < 0) {
// Defensive: prevent negative due to unexpected double-decrement
numInUseStreams = 0;
}

boolean nowInUseStream = numInUseStreams > 0;
if(nowInUseStream != listenerInUse) {
listenerInUse = nowInUseStream;
clientTransportListener.transportInUse(nowInUseStream);
}
}

@GuardedBy("this")
@Override
protected void handlePingResponse(Parcel parcel) {
Expand Down
Loading