1
0
Fork 0
mirror of https://github.com/vanitasvitae/Smack.git synced 2024-11-25 13:32:07 +01:00

Make SynchronizationPoint interruptible

SMACK-632
This commit is contained in:
Florian Schmaus 2015-04-12 18:33:43 +02:00
parent 4a16ab9329
commit 189f524195
3 changed files with 13 additions and 18 deletions

View file

@ -132,7 +132,7 @@ public class XMPPBOSHConnection extends AbstractXMPPConnection {
} }
@Override @Override
protected void connectInternal() throws SmackException { protected void connectInternal() throws SmackException, InterruptedException {
done = false; done = false;
try { try {
// Ensure a clean starting state // Ensure a clean starting state

View file

@ -19,8 +19,6 @@ package org.jivesoftware.smack;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.Lock;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.jivesoftware.smack.SmackException.NoResponseException; import org.jivesoftware.smack.SmackException.NoResponseException;
import org.jivesoftware.smack.SmackException.NotConnectedException; import org.jivesoftware.smack.SmackException.NotConnectedException;
@ -30,8 +28,6 @@ import org.jivesoftware.smack.packet.PlainStreamElement;
public class SynchronizationPoint<E extends Exception> { public class SynchronizationPoint<E extends Exception> {
private static final Logger LOGGER = Logger.getLogger(SynchronizationPoint.class.getName());
private final AbstractXMPPConnection connection; private final AbstractXMPPConnection connection;
private final Lock connectionLock; private final Lock connectionLock;
private final Condition condition; private final Condition condition;
@ -120,8 +116,9 @@ public class SynchronizationPoint<E extends Exception> {
* Check if this synchronization point is successful or wait the connections reply timeout. * Check if this synchronization point is successful or wait the connections reply timeout.
* @throws NoResponseException if there was no response marking the synchronization point as success or failed. * @throws NoResponseException if there was no response marking the synchronization point as success or failed.
* @throws E if there was a failure * @throws E if there was a failure
* @throws InterruptedException
*/ */
public void checkIfSuccessOrWaitOrThrow() throws NoResponseException, E { public void checkIfSuccessOrWaitOrThrow() throws NoResponseException, E, InterruptedException {
checkIfSuccessOrWait(); checkIfSuccessOrWait();
if (state == State.Failure) { if (state == State.Failure) {
throw failureException; throw failureException;
@ -131,8 +128,9 @@ public class SynchronizationPoint<E extends Exception> {
/** /**
* Check if this synchronization point is successful or wait the connections reply timeout. * Check if this synchronization point is successful or wait the connections reply timeout.
* @throws NoResponseException if there was no response marking the synchronization point as success or failed. * @throws NoResponseException if there was no response marking the synchronization point as success or failed.
* @throws InterruptedException
*/ */
public void checkIfSuccessOrWait() throws NoResponseException { public void checkIfSuccessOrWait() throws NoResponseException, InterruptedException {
connectionLock.lock(); connectionLock.lock();
try { try {
if (state == State.Success) { if (state == State.Success) {
@ -222,20 +220,16 @@ public class SynchronizationPoint<E extends Exception> {
* {@link #reportSuccess()}, {@link #reportFailure()} and {@link #reportFailure(Exception)} will either set this * {@link #reportSuccess()}, {@link #reportFailure()} and {@link #reportFailure(Exception)} will either set this
* synchronization point to {@link State#Success} or {@link State#Failure}. If none of them is set after the * synchronization point to {@link State#Success} or {@link State#Failure}. If none of them is set after the
* connections reply timeout, this method will set the state of {@link State#NoResponse}. * connections reply timeout, this method will set the state of {@link State#NoResponse}.
* @throws InterruptedException
*/ */
private void waitForConditionOrTimeout() { private void waitForConditionOrTimeout() throws InterruptedException {
long remainingWait = TimeUnit.MILLISECONDS.toNanos(connection.getPacketReplyTimeout()); long remainingWait = TimeUnit.MILLISECONDS.toNanos(connection.getPacketReplyTimeout());
while (state == State.RequestSent || state == State.Initial) { while (state == State.RequestSent || state == State.Initial) {
try {
if (remainingWait <= 0) { if (remainingWait <= 0) {
state = State.NoResponse; state = State.NoResponse;
break; break;
} }
remainingWait = condition.awaitNanos(remainingWait); remainingWait = condition.awaitNanos(remainingWait);
} catch (InterruptedException e) {
// This InterruptedException could be "spurious wakeups", see javadoc of awaitNanos()
LOGGER.log(Level.WARNING, "Thread interrupt while waiting for condition or timeout ignored", e);
}
} }
} }

View file

@ -1239,6 +1239,7 @@ public class XMPPTCPConnection extends AbstractXMPPConnection {
/** /**
* Shuts down the stanza(/packet) writer. Once this method has been called, no further * Shuts down the stanza(/packet) writer. Once this method has been called, no further
* packets will be written to the server. * packets will be written to the server.
* @throws InterruptedException
*/ */
void shutdown(boolean instant) { void shutdown(boolean instant) {
instantShutdown = instant; instantShutdown = instant;
@ -1247,7 +1248,7 @@ public class XMPPTCPConnection extends AbstractXMPPConnection {
try { try {
shutdownDone.checkIfSuccessOrWait(); shutdownDone.checkIfSuccessOrWait();
} }
catch (NoResponseException e) { catch (NoResponseException | InterruptedException e) {
LOGGER.log(Level.WARNING, "shutdownDone was not marked as successful by the writer thread", e); LOGGER.log(Level.WARNING, "shutdownDone was not marked as successful by the writer thread", e);
} }
} }