View Javadoc

1   package cz.cuni.amis.utils.future;
2   
3   import java.util.concurrent.TimeUnit;
4   
5   import cz.cuni.amis.utils.exception.PogamutCancellationException;
6   import cz.cuni.amis.utils.exception.PogamutInterruptedException;
7   import cz.cuni.amis.utils.exception.PogamutTimeoutException;
8   import cz.cuni.amis.utils.flag.Flag;
9   import cz.cuni.amis.utils.flag.WaitForFlagChange;
10  
11  public abstract class RunnableFuture<RESULT> implements Runnable, IFuture<RESULT> {
12  	
13  	private Object mutex = new Object();
14  	
15  	private boolean cancelled = false;
16  	
17  	private boolean running = false;
18  	
19  	private Flag<Boolean> done = new Flag<Boolean>(false);
20  
21  	private RuntimeException exception = null;
22  
23  	private RESULT result = null;
24  	
25  	/**
26  	 * Provide the implementation of your work that returns some RESULT or throws an exception if something happens.
27  	 * @return
28  	 */
29  	protected abstract RESULT process() throws Exception;
30  	
31  	@Override
32  	public final void run() {
33  		synchronized(mutex) {
34  			if (cancelled) return;
35  			running = true;
36  		}
37  		try {
38  			result = process();
39  		} catch (RuntimeException e) {
40  			exception = e;
41  		} catch (Exception e) {
42  			exception = new RuntimeException(e);
43  		}
44  		synchronized(mutex) {
45  			running = false;
46  			done.setFlag(true);
47  		}
48  	}
49  	
50  	@Override
51  	public final boolean cancel(boolean mayInterruptIfRunning) {
52  		synchronized(mutex) {
53  			if (done.getFlag()) return false;
54  			if (running) return false;
55  			cancelled = true;
56  		}
57  		return true;
58  	}
59  	
60  	private RESULT getResult() {
61  		if (exception != null) throw exception;
62  		if (cancelled) throw new PogamutCancellationException("request has been cancelled", this);
63  		return result;
64  	}
65  
66  	@Override
67  	public final RESULT get() {
68  		synchronized(mutex) {
69  			if (done.getFlag()) return getResult();
70  		}
71  		new WaitForFlagChange<Boolean>(done, true).await();
72  		return getResult();
73  	}
74  
75  	@Override
76  	public final RESULT get(long timeout, TimeUnit unit) throws PogamutInterruptedException, PogamutTimeoutException {
77  		synchronized(mutex) {
78  			if (done.getFlag()) return getResult();
79  		}
80  		new WaitForFlagChange<Boolean>(done, true).await(timeout, unit);
81  		synchronized(mutex) {
82  			if (!done.getFlag()) return getResult();
83  			return getResult();
84  		}
85  	}
86  
87  	@Override
88  	public final boolean isCancelled() {
89  		return cancelled;
90  	}
91  
92  	@Override
93  	public final boolean isDone() {
94  		return done.getFlag();
95  	}
96  	
97  }