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
27
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 }