Improve synchronization for "task" field in BaseCommand

The use an AtomicReference to guard access to the task field.

Change-Id: Ic1777192df040994ee29f0c59eea35b7ca3972b0
This commit is contained in:
Colby Ranger
2012-05-08 10:43:15 -07:00
parent 12c1f53b7b
commit 95b6eb3ec7

View File

@@ -14,6 +14,7 @@
package com.google.gerrit.sshd;
import com.google.common.util.concurrent.Atomics;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.reviewdb.client.Project.NameKey;
import com.google.gerrit.server.CurrentUser;
@@ -50,6 +51,7 @@ import java.io.PrintWriter;
import java.io.StringWriter;
import java.io.UnsupportedEncodingException;
import java.util.concurrent.Future;
import java.util.concurrent.atomic.AtomicReference;
public abstract class BaseCommand implements Command {
private static final Logger log = LoggerFactory.getLogger(BaseCommand.class);
@@ -87,7 +89,7 @@ public abstract class BaseCommand implements Command {
private Provider<SshScope.Context> contextProvider;
/** The task, as scheduled on a worker thread. */
private Future<?> task;
private final AtomicReference<Future<?>> task;
/** Text of the command line which lead up to invoking this instance. */
private String commandName = "";
@@ -95,6 +97,10 @@ public abstract class BaseCommand implements Command {
/** Unparsed command line options. */
private String[] argv;
public BaseCommand() {
task = Atomics.newReference();
}
public void setInputStream(final InputStream in) {
this.in = in;
}
@@ -121,8 +127,9 @@ public abstract class BaseCommand implements Command {
@Override
public void destroy() {
if (task != null && !task.isDone()) {
task.cancel(true);
Future<?> future = task.getAndSet(null);
if (future != null && !future.isDone()) {
future.cancel(true);
}
}
@@ -243,7 +250,7 @@ public abstract class BaseCommand implements Command {
* @param thunk the runnable to execute on the thread, performing the
* command's logic.
*/
protected synchronized void startThread(final CommandRunnable thunk) {
protected void startThread(final CommandRunnable thunk) {
final TaskThunk tt = new TaskThunk(thunk);
if (isAdminCommand() || (isAdminHighPriorityCommand()
@@ -254,7 +261,7 @@ public abstract class BaseCommand implements Command {
//
new Thread(tt, tt.toString()).start();
} else {
task = executor.submit(tt);
task.set(executor.submit(tt));
}
}