mirror of https://github.com/grpc/grpc-java.git
Remove Intrinsic locking in ChannelImpl.
This commit is contained in:
parent
e36a64e6a6
commit
4d2b3e3d06
|
|
@ -62,6 +62,7 @@ public final class ChannelImpl extends Channel {
|
||||||
private final ClientTransportFactory transportFactory;
|
private final ClientTransportFactory transportFactory;
|
||||||
private final ExecutorService executor;
|
private final ExecutorService executor;
|
||||||
private final String userAgent;
|
private final String userAgent;
|
||||||
|
private final Object lock = new Object();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Executor that runs deadline timers for requests.
|
* Executor that runs deadline timers for requests.
|
||||||
|
|
@ -77,16 +78,16 @@ public final class ChannelImpl extends Channel {
|
||||||
* present, but previously used transports that still have streams or are stopping may also be
|
* present, but previously used transports that still have streams or are stopping may also be
|
||||||
* present.
|
* present.
|
||||||
*/
|
*/
|
||||||
@GuardedBy("this")
|
@GuardedBy("lock")
|
||||||
private Collection<ClientTransport> transports = new ArrayList<ClientTransport>();
|
private Collection<ClientTransport> transports = new ArrayList<ClientTransport>();
|
||||||
/**
|
/**
|
||||||
* The transport for new outgoing requests. 'this' lock must be held when assigning to
|
* The transport for new outgoing requests. 'this' lock must be held when assigning to
|
||||||
* activeTransport.
|
* activeTransport.
|
||||||
*/
|
*/
|
||||||
private volatile ClientTransport activeTransport;
|
private volatile ClientTransport activeTransport;
|
||||||
@GuardedBy("this")
|
@GuardedBy("lock")
|
||||||
private boolean shutdown;
|
private boolean shutdown;
|
||||||
@GuardedBy("this")
|
@GuardedBy("lock")
|
||||||
private boolean terminated;
|
private boolean terminated;
|
||||||
private Runnable terminationRunnable;
|
private Runnable terminationRunnable;
|
||||||
|
|
||||||
|
|
@ -116,25 +117,27 @@ public final class ChannelImpl extends Channel {
|
||||||
* Initiates an orderly shutdown in which preexisting calls continue but new calls are immediately
|
* Initiates an orderly shutdown in which preexisting calls continue but new calls are immediately
|
||||||
* cancelled.
|
* cancelled.
|
||||||
*/
|
*/
|
||||||
public synchronized ChannelImpl shutdown() {
|
public ChannelImpl shutdown() {
|
||||||
if (shutdown) {
|
synchronized (lock) {
|
||||||
|
if (shutdown) {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
shutdown = true;
|
||||||
|
// After shutdown there are no new calls, so no new cancellation tasks are needed
|
||||||
|
deadlineCancellationExecutor =
|
||||||
|
SharedResourceHolder.release(TIMER_SERVICE, deadlineCancellationExecutor);
|
||||||
|
if (activeTransport != null) {
|
||||||
|
activeTransport.shutdown();
|
||||||
|
activeTransport = null;
|
||||||
|
} else if (transports.isEmpty()) {
|
||||||
|
terminated = true;
|
||||||
|
lock.notifyAll();
|
||||||
|
if (terminationRunnable != null) {
|
||||||
|
terminationRunnable.run();
|
||||||
|
}
|
||||||
|
}
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
shutdown = true;
|
|
||||||
// After shutdown there are no new calls, so no new cancellation tasks are needed
|
|
||||||
deadlineCancellationExecutor =
|
|
||||||
SharedResourceHolder.release(TIMER_SERVICE, deadlineCancellationExecutor);
|
|
||||||
if (activeTransport != null) {
|
|
||||||
activeTransport.shutdown();
|
|
||||||
activeTransport = null;
|
|
||||||
} else if (transports.isEmpty()) {
|
|
||||||
terminated = true;
|
|
||||||
notifyAll();
|
|
||||||
if (terminationRunnable != null) {
|
|
||||||
terminationRunnable.run();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -145,9 +148,11 @@ public final class ChannelImpl extends Channel {
|
||||||
* <p>NOT YET IMPLEMENTED. This method currently behaves identically to shutdown().
|
* <p>NOT YET IMPLEMENTED. This method currently behaves identically to shutdown().
|
||||||
*/
|
*/
|
||||||
// TODO(ejona86): cancel preexisting calls.
|
// TODO(ejona86): cancel preexisting calls.
|
||||||
public synchronized ChannelImpl shutdownNow() {
|
public ChannelImpl shutdownNow() {
|
||||||
shutdown();
|
synchronized (lock) {
|
||||||
return this;
|
shutdown();
|
||||||
|
return this;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -157,8 +162,10 @@ public final class ChannelImpl extends Channel {
|
||||||
* @see #shutdown()
|
* @see #shutdown()
|
||||||
* @see #isTerminated()
|
* @see #isTerminated()
|
||||||
*/
|
*/
|
||||||
public synchronized boolean isShutdown() {
|
public boolean isShutdown() {
|
||||||
return shutdown;
|
synchronized (lock) {
|
||||||
|
return shutdown;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -166,14 +173,15 @@ public final class ChannelImpl extends Channel {
|
||||||
*
|
*
|
||||||
* @return whether the channel is terminated, as would be done by {@link #isTerminated()}.
|
* @return whether the channel is terminated, as would be done by {@link #isTerminated()}.
|
||||||
*/
|
*/
|
||||||
public synchronized boolean awaitTerminated(long timeout, TimeUnit unit)
|
public boolean awaitTerminated(long timeout, TimeUnit unit) throws InterruptedException {
|
||||||
throws InterruptedException {
|
synchronized (lock) {
|
||||||
long timeoutNanos = unit.toNanos(timeout);
|
long timeoutNanos = unit.toNanos(timeout);
|
||||||
long endTimeNanos = System.nanoTime() + timeoutNanos;
|
long endTimeNanos = System.nanoTime() + timeoutNanos;
|
||||||
while (!terminated && (timeoutNanos = endTimeNanos - System.nanoTime()) > 0) {
|
while (!terminated && (timeoutNanos = endTimeNanos - System.nanoTime()) > 0) {
|
||||||
TimeUnit.NANOSECONDS.timedWait(this, timeoutNanos);
|
TimeUnit.NANOSECONDS.timedWait(lock, timeoutNanos);
|
||||||
|
}
|
||||||
|
return terminated;
|
||||||
}
|
}
|
||||||
return terminated;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -182,8 +190,10 @@ public final class ChannelImpl extends Channel {
|
||||||
*
|
*
|
||||||
* @see #isShutdown()
|
* @see #isShutdown()
|
||||||
*/
|
*/
|
||||||
public synchronized boolean isTerminated() {
|
public boolean isTerminated() {
|
||||||
return terminated;
|
synchronized (lock) {
|
||||||
|
return terminated;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -224,7 +234,7 @@ public final class ChannelImpl extends Channel {
|
||||||
if (savedActiveTransport != null) {
|
if (savedActiveTransport != null) {
|
||||||
return savedActiveTransport;
|
return savedActiveTransport;
|
||||||
}
|
}
|
||||||
synchronized (this) {
|
synchronized (lock) {
|
||||||
if (shutdown) {
|
if (shutdown) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
@ -277,7 +287,7 @@ public final class ChannelImpl extends Channel {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void transportShutdown() {
|
public void transportShutdown() {
|
||||||
synchronized (ChannelImpl.this) {
|
synchronized (lock) {
|
||||||
if (activeTransport == transport) {
|
if (activeTransport == transport) {
|
||||||
activeTransport = null;
|
activeTransport = null;
|
||||||
}
|
}
|
||||||
|
|
@ -286,7 +296,7 @@ public final class ChannelImpl extends Channel {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void transportTerminated() {
|
public void transportTerminated() {
|
||||||
synchronized (ChannelImpl.this) {
|
synchronized (lock) {
|
||||||
if (activeTransport == transport) {
|
if (activeTransport == transport) {
|
||||||
log.warning("transportTerminated called without previous transportShutdown");
|
log.warning("transportTerminated called without previous transportShutdown");
|
||||||
activeTransport = null;
|
activeTransport = null;
|
||||||
|
|
@ -298,7 +308,7 @@ public final class ChannelImpl extends Channel {
|
||||||
log.warning("transportTerminated called after already terminated");
|
log.warning("transportTerminated called after already terminated");
|
||||||
}
|
}
|
||||||
terminated = true;
|
terminated = true;
|
||||||
ChannelImpl.this.notifyAll();
|
lock.notifyAll();
|
||||||
if (terminationRunnable != null) {
|
if (terminationRunnable != null) {
|
||||||
terminationRunnable.run();
|
terminationRunnable.run();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue