001package org.cache2k.impl.threading; 002 003/* 004 * #%L 005 * cache2k core package 006 * %% 007 * Copyright (C) 2000 - 2015 headissue GmbH, Munich 008 * %% 009 * This program is free software: you can redistribute it and/or modify 010 * it under the terms of the GNU General Public License as 011 * published by the Free Software Foundation, either version 3 of the 012 * License, or (at your option) any later version. 013 * 014 * This program is distributed in the hope that it will be useful, 015 * but WITHOUT ANY WARRANTY; without even the implied warranty of 016 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 017 * GNU General Public License for more details. 018 * 019 * You should have received a copy of the GNU General Public 020 * License along with this program. If not, see 021 * <http://www.gnu.org/licenses/gpl-3.0.html>. 022 * #L% 023 */ 024 025import java.util.Iterator; 026import java.util.LinkedList; 027import java.util.List; 028import java.util.concurrent.ExecutionException; 029import java.util.concurrent.Future; 030import java.util.concurrent.TimeUnit; 031import java.util.concurrent.TimeoutException; 032 033/** 034 * @author Jens Wilke; created: 2014-06-03 035 */ 036public class Futures { 037 038 /** 039 * A container for futures which waits for all futures to finish. 040 * Futures to wait for can be added with {@link #add(java.util.concurrent.Future)} 041 * or the constructor. Waiting for all futures to finish is done 042 * via {@link #get()}. 043 * 044 * <p/>The get method call will throw Exceptions from the added futures. 045 */ 046 public static class WaitForAllFuture<V> implements Future<V> { 047 048 List<Future<V>> futureList = new LinkedList<Future<V>>(); 049 050 public WaitForAllFuture(Future<V> _top) { 051 add(_top); 052 } 053 054 @SafeVarargs 055 public WaitForAllFuture(final Future<V>... _top) { 056 for (Future<V> f : _top) { add(f); } 057 } 058 059 /** 060 * Add a new future to the list for Futures we should wait for. 061 */ 062 public synchronized void add(Future<V> f) { 063 if (f == null) { return; } 064 futureList.add(f); 065 } 066 067 /** 068 * Send cancel to all futures that are not yet cancelled. Returns 069 * true if every future is in cancelled state. 070 */ 071 @Override 072 public synchronized boolean cancel(boolean mayInterruptIfRunning) { 073 if (futureList.size() == 0) { 074 return false; 075 } 076 boolean _flag = true; 077 for (Future<V> f : futureList) { 078 if (!f.isCancelled()) { 079 f.cancel(mayInterruptIfRunning); 080 _flag &= f.isCancelled(); 081 } 082 } 083 return _flag; 084 } 085 086 /** 087 * Unsupported, it is not possible to implement useful semantics. 088 */ 089 @Override 090 public boolean isCancelled() { 091 throw new UnsupportedOperationException(); 092 } 093 094 /** 095 * True, if every future is done or no future is contained. 096 * 097 * <p/>The list of futures is not touched, since an exception 098 * may be thrown via get. 099 */ 100 @Override 101 public synchronized boolean isDone() { 102 boolean _flag = true; 103 for (Future<V> f : futureList) { 104 _flag &= f.isDone(); 105 } 106 return _flag; 107 } 108 109 /** 110 * Wait until everything is finished. It may happen that a new future during 111 * this method waits for finishing another one. If this happens, we wait 112 * for that task also. 113 * 114 * <p/>All get methods of the futures are executed to probe for possible 115 * exceptions. Futures completed without exceptions, will be removed 116 * for the list. 117 * 118 * <p/>Implementation is a bit tricky. We need to call a potential stalling 119 * get outside the synchronized block, since new futures may come in in parallel. 120 */ 121 @Override 122 public V get() throws InterruptedException, ExecutionException { 123 for (;;) { 124 Future<V> _needsGet = null; 125 synchronized (this) { 126 Iterator<Future<V>> it = futureList.iterator(); 127 while (it.hasNext()){ 128 Future<V> f = it.next(); 129 if (!f.isDone()) { 130 _needsGet = f; 131 break; 132 } 133 f.get(); 134 it.remove(); 135 } 136 } 137 if (_needsGet != null) { 138 _needsGet.get(); 139 continue; 140 } 141 return null; 142 } 143 } 144 145 @Override 146 public V get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException { 147 long _maxTime = System.currentTimeMillis() + unit.toMillis(timeout); 148 if (_maxTime < 0) { 149 return get(); 150 } 151 for (;;) { 152 Future<V> _needsGet = null; 153 synchronized (this) { 154 Iterator<Future<V>> it = futureList.iterator(); 155 while (it.hasNext()){ 156 Future<V> f = it.next(); 157 if (!f.isDone()) { 158 _needsGet = f; 159 break; 160 } 161 f.get(); 162 it.remove(); 163 } 164 } 165 if (_needsGet != null) { 166 long now = System.currentTimeMillis(); 167 long _waitTime = _maxTime - now; 168 if (_waitTime <= 0) { 169 throw new TimeoutException(); 170 } 171 _needsGet.get(_maxTime - now, TimeUnit.MILLISECONDS); 172 continue; 173 } 174 return null; 175 } 176 } 177 178 } 179 180 public static class FinishedFuture<V> implements Future<V> { 181 182 V result; 183 184 public FinishedFuture() { 185 } 186 187 public FinishedFuture(V result) { 188 this.result = result; 189 } 190 191 @Override 192 public boolean cancel(boolean mayInterruptIfRunning) { 193 return false; 194 } 195 196 @Override 197 public boolean isCancelled() { 198 return false; 199 } 200 201 @Override 202 public boolean isDone() { 203 return true; 204 } 205 206 @Override 207 public V get() { 208 return result; 209 } 210 211 @Override 212 public V get(long timeout, TimeUnit unit) { 213 return result; 214 } 215 } 216 217 public static class ExceptionFuture<V> implements Future<V> { 218 219 private Throwable exception; 220 221 public ExceptionFuture(Throwable exception) { 222 this.exception = exception; 223 } 224 225 @Override 226 public boolean cancel(boolean mayInterruptIfRunning) { 227 return false; 228 } 229 230 @Override 231 public boolean isCancelled() { 232 return false; 233 } 234 235 @Override 236 public boolean isDone() { 237 return true; 238 } 239 240 @Override 241 public V get() throws ExecutionException { 242 throw new ExecutionException(exception); 243 } 244 245 @Override 246 public V get(long timeout, TimeUnit unit) throws ExecutionException { 247 throw new ExecutionException(exception); 248 } 249 250 } 251 252 public static abstract class BusyWaitFuture<V> implements Future<V> { 253 254 private int spinMillis = 123; 255 private V result = null; 256 257 protected BusyWaitFuture() { } 258 259 protected BusyWaitFuture(V _defaultResult) { 260 this.result = _defaultResult; 261 } 262 263 protected BusyWaitFuture(int spinMillis, V _defaultResult) { 264 this.spinMillis = spinMillis; 265 this.result = _defaultResult; 266 } 267 268 protected V getResult() { return result; } 269 270 @Override 271 public boolean cancel(boolean mayInterruptIfRunning) { return false; } 272 273 @Override 274 public boolean isCancelled() { return false; } 275 276 @Override 277 public abstract boolean isDone(); 278 279 /** Just busy wait for running fetches. We have no notification for this. */ 280 @Override 281 public V get() throws InterruptedException, ExecutionException { 282 while (!isDone()) { Thread.sleep(spinMillis); } 283 return getResult(); 284 } 285 286 @Override 287 public V get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException { 288 long _maxMillis = unit.toMillis(timeout) + System.currentTimeMillis(); 289 if (_maxMillis < 0) { return get(); } 290 while (!isDone() && System.currentTimeMillis() < _maxMillis) { Thread.sleep(spinMillis); } 291 if (!isDone()) { throw new TimeoutException(); } 292 return getResult(); 293 } 294 295 } 296 297}