2 * Copyright 2005-2010 the original author or authors.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
16 package org.wamblee.cache;
19 * Utility class to deal with recomputation of a certain value. The goal is to
20 * have only one thread at a time compute the value while other threads that
21 * simulateneously detect recomputation continue with the old value.
24 * @author Erik Brakkee
28 public class ComputedValue<T> {
34 * Type of object to compute.
36 public static interface Computation<T> {
38 * Checks whether the object is out of date. This will be invoked while
39 * holding the lock passed at construction of the compute guard.
41 * Any runtime exceptions thrown are passed back through the
42 * {@link ComputedValue#get()}.
44 * @return True iff recomputation is necessary.
46 boolean isOutOfDate();
49 * Computes the object. This will be invoked while <em>not</em> holding
50 * the lock passed at construction of the compute guard. It is
51 * guaranteed that per ComputeGuard, no concurrent calls to compute()
54 * Any runtime exceptions thrown are passed back through the
55 * {@link ComputedValue#get()}.
57 * @return Computed object.
63 private Computation<T> computedValue;
69 * Constructs the compute guard
72 * Lock to use during computation and to guard the value.
76 public ComputedValue(Object aLock, Computation aComputation) {
78 computedValue = aComputation;
84 * Triggers computation of the value (if no other thread is currently
85 * computing the value).
87 public void compute() {
90 return; // another thread is already taking care of it.
95 T newvalue = computedValue.compute();
105 * Gets the current value of the object, recomputing it if the object is out
106 * of date. This method ensures that only one thread at a time will do
109 * @return Current value.
112 boolean mustCompute = false;
113 synchronized (lock) {
114 if (computedValue.isOutOfDate()) {
121 synchronized (lock) {
127 * Gets the currently cached value. No recomputation is performed.
129 * @return Cached value.
131 public T getCached() {
132 synchronized (lock) {
139 * Sets the value explicitly.
144 public void set(T aValue) {
145 synchronized (lock) {