source:
java/main/src/main/java/com/framsticks/util/dispatching/Dispatching.java
@
96
Last change on this file since 96 was 96, checked in by , 11 years ago | |
---|---|
File size: 4.9 KB |
Rev | Line | |
---|---|---|
[84] | 1 | package com.framsticks.util.dispatching; |
2 | ||
[88] | 3 | import org.apache.log4j.Logger; |
4 | ||
[96] | 5 | import com.framsticks.util.FramsticksException; |
[84] | 6 | import com.framsticks.util.StateFunctor; |
7 | ||
8 | /** | |
9 | * @author Piotr Sniegowski | |
10 | */ | |
11 | public abstract class Dispatching { | |
[88] | 12 | private static final Logger log = Logger.getLogger(Dispatching.class); |
[84] | 13 | |
[85] | 14 | public static boolean isThreadSafe() { |
15 | return true; | |
16 | } | |
[84] | 17 | |
[90] | 18 | public static <C> void dispatchIfNotActive(Dispatcher<C> dispatcher, RunAt<? extends C> runnable) { |
[85] | 19 | if (dispatcher.isActive()) { |
20 | runnable.run(); | |
21 | return; | |
22 | } | |
[90] | 23 | dispatcher.dispatch(runnable); |
[85] | 24 | } |
[84] | 25 | |
[85] | 26 | //TODO RunAt StateFunctor |
27 | public static <C> void dispatchOk(Dispatcher<C> dispatcher, final StateFunctor stateFunctor) { | |
[90] | 28 | dispatcher.dispatch(new RunAt<C>() { |
[85] | 29 | @Override |
30 | public void run() { | |
[96] | 31 | stateFunctor.call(); |
[85] | 32 | } |
33 | }); | |
34 | } | |
[84] | 35 | |
[85] | 36 | // public static boolean assertInvokeLater(Dispatcher dispatcher, RunAt runnable) { |
[88] | 37 | // dispatcher.invokeLater(runnable); |
38 | // return true; | |
[85] | 39 | // } |
[84] | 40 | |
[85] | 41 | public static <P, C> void invokeDispatch(Dispatcher<P> dispatcher, final Dispatcher<C> finalDispatcher, final RunAt<C> runnable) { |
[90] | 42 | dispatcher.dispatch(new RunAt<P>() { |
[85] | 43 | @Override |
44 | public void run() { | |
[90] | 45 | finalDispatcher.dispatch(runnable); |
[85] | 46 | } |
47 | }); | |
48 | } | |
[84] | 49 | |
[90] | 50 | public static void sleep(double seconds) { |
[88] | 51 | try { |
[90] | 52 | java.lang.Thread.sleep((long) (seconds * 1000)); |
[88] | 53 | } catch (InterruptedException e) { |
54 | ||
55 | } | |
56 | } | |
57 | ||
58 | @SuppressWarnings("unchecked") | |
59 | public static void dispatcherGuardedInvoke(Joinable joinable, RunAt<?> runnable) { | |
60 | if (joinable instanceof Dispatcher) { | |
[90] | 61 | dispatchIfNotActive(Dispatcher.class.cast(joinable), runnable); |
[88] | 62 | return; |
63 | } | |
64 | runnable.run(); | |
65 | } | |
66 | ||
67 | public static void use(final Joinable joinable, final JoinableParent owner) { | |
68 | log.debug("using " + joinable + " by " + owner); | |
69 | if (joinable.use(owner)) { | |
70 | log.debug("started " + joinable); | |
71 | } else { | |
72 | log.debug("start of " + joinable + " already happened"); | |
73 | } | |
74 | } | |
75 | ||
76 | public static void drop(final Joinable joinable, final JoinableParent owner) { | |
77 | log.debug("droping " + joinable + " by " + owner); | |
78 | if (joinable.drop(owner)) { | |
79 | log.debug("stoped " + joinable); | |
80 | } else { | |
81 | log.debug("stop of " + joinable + " deferred"); | |
82 | } | |
83 | } | |
84 | ||
85 | public static void join(Joinable joinable) throws InterruptedException { | |
86 | log.debug("joining " + joinable); | |
87 | try { | |
88 | joinable.join(); | |
89 | } catch (InterruptedException e) { | |
90 | log.debug("failed to join " + joinable); | |
91 | throw e; | |
92 | } | |
93 | log.debug("joined " + joinable); | |
94 | } | |
95 | ||
96 | public static void childChangedState(final JoinableParent parent, final Joinable joinable, final JoinableState state) { | |
97 | dispatcherGuardedInvoke(joinable, new RunAt<Object>() { | |
98 | @Override | |
99 | public void run() { | |
100 | log.debug("joinable " + joinable + " is notifying parent " + parent + " about change to " + state); | |
101 | parent.childChangedState(joinable, state); | |
102 | } | |
103 | }); | |
104 | } | |
105 | ||
106 | public static void wait(Object object, long millis) { | |
107 | try { | |
[90] | 108 | synchronized (object) { |
109 | object.wait(millis); | |
110 | } | |
[88] | 111 | } catch (InterruptedException e) { |
112 | } | |
113 | } | |
114 | ||
115 | public static void joinAbsolutely(Joinable joinable) { | |
[90] | 116 | log.debug("joining absolutely " + joinable); |
[88] | 117 | while (true) { |
118 | try { | |
119 | Dispatching.join(joinable); | |
120 | return; | |
121 | } catch (InterruptedException e) { | |
122 | // throw new FramsticksException().msg("failed to join").arg("dispatcher", dispatcher).cause(e); | |
123 | } | |
[90] | 124 | log.debug("waiting for " + joinable); |
125 | wait(joinable, 500); | |
[88] | 126 | } |
127 | } | |
128 | ||
[90] | 129 | public interface Query<T> { |
130 | T get(); | |
131 | } | |
[88] | 132 | |
[90] | 133 | public static class QueryRunner<T, C> extends RunAt<C> { |
134 | protected final Query<T> query; | |
135 | T result; | |
136 | boolean ready = false; | |
[88] | 137 | |
[90] | 138 | /** |
139 | * @param query | |
140 | */ | |
141 | public QueryRunner(Query<T> query) { | |
142 | this.query = query; | |
143 | } | |
[88] | 144 | |
[90] | 145 | @Override |
146 | public void run() { | |
147 | result = query.get(); | |
148 | synchronized (this) { | |
149 | ready = true; | |
150 | this.notifyAll(); | |
151 | } | |
152 | } | |
153 | ||
154 | public T get() { | |
155 | synchronized (this) { | |
156 | while (!ready) { | |
157 | try { | |
158 | this.wait(100); | |
159 | } catch (InterruptedException e) { | |
160 | } | |
161 | } | |
162 | } | |
163 | return result; | |
164 | } | |
165 | } | |
166 | ||
167 | public static <T, C> T get(Dispatcher<C> dispatcher, Query<T> query) { | |
168 | QueryRunner<T, C> runner = new QueryRunner<T, C>(query); | |
169 | dispatcher.dispatch(runner); | |
170 | return runner.get(); | |
171 | } | |
172 | ||
[96] | 173 | public static class Waiter { |
174 | protected boolean done = false; | |
[90] | 175 | |
[96] | 176 | protected final double timeOut; |
[90] | 177 | |
[96] | 178 | /** |
179 | * @param timeOut | |
180 | */ | |
181 | public Waiter(double timeOut) { | |
182 | this.timeOut = timeOut; | |
183 | } | |
184 | ||
185 | public synchronized void pass() { | |
186 | done = true; | |
187 | this.notify(); | |
188 | } | |
189 | ||
190 | public synchronized void waitFor() { | |
191 | long end = System.currentTimeMillis() + (int)(timeOut * 1000); | |
192 | while ((!done) && System.currentTimeMillis() < end) { | |
193 | try { | |
194 | this.wait(end - System.currentTimeMillis()); | |
195 | } catch (InterruptedException e) { | |
196 | break; | |
197 | } | |
198 | } | |
199 | if (!done) { | |
200 | throw new FramsticksException().msg("waiter timed out"); | |
201 | } | |
202 | } | |
203 | } | |
204 | ||
205 | ||
206 | public static <C> void synchronize(Dispatcher<C> dispatcher, double seconds) { | |
207 | final Waiter waiter = new Waiter(seconds); | |
208 | dispatcher.dispatch(new RunAt<C>() { | |
209 | @Override | |
210 | public void run() { | |
211 | waiter.pass(); | |
212 | } | |
213 | }); | |
214 | waiter.waitFor(); | |
215 | } | |
216 | ||
[84] | 217 | } |
Note: See TracBrowser
for help on using the repository browser.