blob: c2dd44824e3e2b3d869abdb7f875393c436af79e [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more contributor license
* agreements. See the NOTICE file distributed with this work for additional information regarding
* copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the License. You may obtain a
* copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied. See the License for the specific language governing permissions and limitations under
* the License.
*/
package org.apache.geode;
/**
* Abstract cancellation proxy for cancelling an operation, esp. a thread.
*
* Creators of services or threads should implement a subclass of CancelCriterion, and implement the
* two methods - cancelInProgress, and generateCancelledException(e).
*
* Code inside the service can check to see if the service is cancelled by calling
* {@link #checkCancelInProgress(Throwable)}. Generally the pattern is to check before performing an
* operation, check if the service is canceled before propagating an exception further up the stack,
* and check for cancellation inside a long loop. Eg.
*
* <pre>
* while (true) {
* c.checkCancelInProgress(null);
* try {
* dispatchEvents();
* } catch (IOException e) {
* c.checkCancelInProgress(e);
* throw e;
* }
* }
* </pre>
*
* @see CancelException
* @since GemFire 5.1
*/
public abstract class CancelCriterion {
/**
* Indicate if the service is in the progress of being cancelled. The typical use of this is to
* indicate, in the case of an {@link InterruptedException}, that the current operation should be
* cancelled.
*
* @return null if the service is not shutting down, or a message that can be used to construct an
* exception indicating the service is shut down.
*/
public abstract String cancelInProgress();
/**
* Use this utility function in your implementation of cancelInProgress() and cancelled() to
* indicate a system failure
*
* @return failure string if system failure has occurred
*/
protected String checkFailure() {
Throwable tilt = SystemFailure.getFailure();
if (tilt != null) {
// Allocate no objects here!
return SystemFailure.JVM_CORRUPTION;
}
return null;
}
/**
* See if the current operation is being cancelled. If so, it either throws a
* {@link RuntimeException} (usually a {@link CancelException}).
*
* @param e an underlying exception or null if there is no exception that triggered this check
* @see #cancelInProgress()
*/
public void checkCancelInProgress(Throwable e) {
SystemFailure.checkFailure();
String reason = cancelInProgress();
if (reason == null) {
return;
}
throw generateCancelledException(e);
}
/**
* Template factory method for generating the exception to be thrown by
* {@link #checkCancelInProgress(Throwable)}. Override this to specify different exception for
* checkCancelInProgress() to throw.
*
* This method should wrap the exception in a service specific CancelationException (eg
* CacheClosedException). or return null if the service is not being canceled.
*
* @param throwable an underlying exception, if any
* @return RuntimeException to be thrown by checkCancelInProgress(), null if the receiver has not
* been cancelled.
*/
public abstract RuntimeException generateCancelledException(Throwable throwable);
/**
* Checks to see if a cancellation is in progress. This is equivalent to the expression
* (cancelInProgress() != null).
*
* @return true if a cancellation is in progress, false if not
*/
public boolean isCancelInProgress() {
return cancelInProgress() != null;
}
}