aboutsummaryrefslogtreecommitdiff
path: root/android/guava/src/com/google/common/util/concurrent/AbstractScheduledService.java
diff options
context:
space:
mode:
Diffstat (limited to 'android/guava/src/com/google/common/util/concurrent/AbstractScheduledService.java')
-rw-r--r--android/guava/src/com/google/common/util/concurrent/AbstractScheduledService.java89
1 files changed, 44 insertions, 45 deletions
diff --git a/android/guava/src/com/google/common/util/concurrent/AbstractScheduledService.java b/android/guava/src/com/google/common/util/concurrent/AbstractScheduledService.java
index 7288ba53d..0b7d34e6b 100644
--- a/android/guava/src/com/google/common/util/concurrent/AbstractScheduledService.java
+++ b/android/guava/src/com/google/common/util/concurrent/AbstractScheduledService.java
@@ -18,10 +18,11 @@ import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.util.concurrent.Futures.immediateCancelledFuture;
import static com.google.common.util.concurrent.MoreExecutors.directExecutor;
+import static com.google.common.util.concurrent.Platform.restoreInterruptIfIsInterruptedException;
import static java.util.Objects.requireNonNull;
import com.google.common.annotations.GwtIncompatible;
-import com.google.common.base.Supplier;
+import com.google.common.annotations.J2ktIncompatible;
import com.google.errorprone.annotations.CanIgnoreReturnValue;
import com.google.errorprone.annotations.concurrent.GuardedBy;
import com.google.j2objc.annotations.WeakOuter;
@@ -98,6 +99,7 @@ import org.checkerframework.checker.nullness.qual.Nullable;
* @since 11.0
*/
@GwtIncompatible
+@J2ktIncompatible
@ElementTypesAreNonnullByDefault
public abstract class AbstractScheduledService implements Service {
private static final Logger logger = Logger.getLogger(AbstractScheduledService.class.getName());
@@ -202,9 +204,11 @@ public abstract class AbstractScheduledService implements Service {
}
AbstractScheduledService.this.runOneIteration();
} catch (Throwable t) {
+ restoreInterruptIfIsInterruptedException(t);
try {
shutDown();
} catch (Exception ignored) {
+ restoreInterruptIfIsInterruptedException(ignored);
logger.log(
Level.WARNING,
"Error while attempting to shut down the service after failure.",
@@ -224,32 +228,28 @@ public abstract class AbstractScheduledService implements Service {
@Override
protected final void doStart() {
executorService =
- MoreExecutors.renamingDecorator(
- executor(),
- new Supplier<String>() {
- @Override
- public String get() {
- return serviceName() + " " + state();
- }
- });
+ MoreExecutors.renamingDecorator(executor(), () -> serviceName() + " " + state());
executorService.execute(
- new Runnable() {
- @Override
- public void run() {
- lock.lock();
- try {
- startUp();
- runningTask = scheduler().schedule(delegate, executorService, task);
- notifyStarted();
- } catch (Throwable t) {
- notifyFailed(t);
- if (runningTask != null) {
- // prevent the task from running if possible
- runningTask.cancel(false);
- }
- } finally {
- lock.unlock();
+ () -> {
+ lock.lock();
+ try {
+ startUp();
+ /*
+ * requireNonNull is safe because executorService is never cleared after the
+ * assignment above.
+ */
+ requireNonNull(executorService);
+ runningTask = scheduler().schedule(delegate, executorService, task);
+ notifyStarted();
+ } catch (Throwable t) {
+ restoreInterruptIfIsInterruptedException(t);
+ notifyFailed(t);
+ if (runningTask != null) {
+ // prevent the task from running if possible
+ runningTask.cancel(false);
}
+ } finally {
+ lock.unlock();
}
});
}
@@ -261,27 +261,25 @@ public abstract class AbstractScheduledService implements Service {
requireNonNull(executorService);
runningTask.cancel(false);
executorService.execute(
- new Runnable() {
- @Override
- public void run() {
+ () -> {
+ try {
+ lock.lock();
try {
- lock.lock();
- try {
- if (state() != State.STOPPING) {
- // This means that the state has changed since we were scheduled. This implies
- // that an execution of runOneIteration has thrown an exception and we have
- // transitioned to a failed state, also this means that shutDown has already
- // been called, so we do not want to call it again.
- return;
- }
- shutDown();
- } finally {
- lock.unlock();
+ if (state() != State.STOPPING) {
+ // This means that the state has changed since we were scheduled. This implies
+ // that an execution of runOneIteration has thrown an exception and we have
+ // transitioned to a failed state, also this means that shutDown has already
+ // been called, so we do not want to call it again.
+ return;
}
- notifyStopped();
- } catch (Throwable t) {
- notifyFailed(t);
+ shutDown();
+ } finally {
+ lock.unlock();
}
+ notifyStopped();
+ } catch (Throwable t) {
+ restoreInterruptIfIsInterruptedException(t);
+ notifyFailed(t);
}
});
}
@@ -347,7 +345,7 @@ public abstract class AbstractScheduledService implements Service {
}
final ScheduledExecutorService executor =
Executors.newSingleThreadScheduledExecutor(new ThreadFactoryImpl());
- // Add a listener to shutdown the executor after the service is stopped. This ensures that the
+ // Add a listener to shut down the executor after the service is stopped. This ensures that the
// JVM shutdown will not be prevented from exiting after this service has stopped or failed.
// Technically this listener is added after start() was called so it is a little gross, but it
// is called within doStart() so we know that the service cannot terminate or fail concurrently
@@ -553,6 +551,7 @@ public abstract class AbstractScheduledService implements Service {
try {
schedule = CustomScheduler.this.getNextSchedule();
} catch (Throwable t) {
+ restoreInterruptIfIsInterruptedException(t);
service.notifyFailed(t);
return new FutureAsCancellable(immediateCancelledFuture());
}
@@ -565,7 +564,7 @@ public abstract class AbstractScheduledService implements Service {
lock.lock();
try {
toReturn = initializeOrUpdateCancellationDelegate(schedule);
- } catch (Throwable e) {
+ } catch (RuntimeException | Error e) {
// If an exception is thrown by the subclass then we need to make sure that the service
// notices and transitions to the FAILED state. We do it by calling notifyFailed directly
// because the service does not monitor the state of the future so if the exception is not