001/*-------------------------------------------------------------------------+ 002| | 003| Copyright 2005-2011 the ConQAT Project | 004| | 005| Licensed under the Apache License, Version 2.0 (the "License"); | 006| you may not use this file except in compliance with the License. | 007| You may obtain a copy of the License at | 008| | 009| http://www.apache.org/licenses/LICENSE-2.0 | 010| | 011| Unless required by applicable law or agreed to in writing, software | 012| distributed under the License is distributed on an "AS IS" BASIS, | 013| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 014| See the License for the specific language governing permissions and | 015| limitations under the License. | 016+-------------------------------------------------------------------------*/ 017package org.conqat.lib.commons.concurrent; 018 019import org.conqat.lib.commons.assertion.CCSMAssert; 020 021/** 022 * A {@link Runnable} that provides a result that can be read asynchronously and 023 * may also throw an exception. 024 * 025 * @param <T> 026 * the return type. 027 * @param <X> 028 * the exception type. 029 */ 030public abstract class RunnableWithAsyncResultBase<T, X extends Throwable> implements Runnable { 031 032 /** The result. */ 033 private T result; 034 035 /** The caught exception. */ 036 private Throwable caughtException = null; 037 038 /** 039 * Flag storing whether execution has finished (and the result is ready). 040 */ 041 private boolean finished = false; 042 043 /** {@inheritDoc} */ 044 @Override 045 public final void run() { 046 try { 047 result = runWithResult(); 048 } catch (Throwable e) { 049 caughtException = e; 050 } 051 finished = true; 052 } 053 054 /** Template method for calculating the result. */ 055 public abstract T runWithResult() throws X; 056 057 /** Returns whether the calculation has been finished. */ 058 public boolean isFinished() { 059 return finished; 060 } 061 062 /** 063 * Returns the result. If the execution threw an exception, this thrown 064 * here. This applies to checked exceptions of type X as well as to runtime 065 * exceptions and errors. If the {@link #run()} method did not terminate 066 * yet, an {@link AssertionError} is thrown. 067 */ 068 @SuppressWarnings("unchecked") 069 public T getResult() throws X { 070 CCSMAssert.isTrue(finished, "Can not query result before run() is finished!"); 071 072 if (caughtException instanceof RuntimeException) { 073 throw (RuntimeException) caughtException; 074 } else if (caughtException instanceof Error) { 075 throw (Error) caughtException; 076 } else if (caughtException != null) { 077 // must be an X in this case 078 throw (X) caughtException; 079 } 080 081 return result; 082 } 083}