Mercurial Hosting > luan
comparison src/org/eclipse/jetty/util/thread/Timeout.java @ 941:c948f674a2d5
simplify Timeout
author | Franklin Schmidt <fschmidt@gmail.com> |
---|---|
date | Tue, 11 Oct 2016 00:34:19 -0600 |
parents | 8e9db0bbf4f9 |
children | c157a786ed0b |
comparison
equal
deleted
inserted
replaced
940:b77d631b9e28 | 941:c948f674a2d5 |
---|---|
31 * The nested class Task should be extended by users of this class to obtain call back notification of | 31 * The nested class Task should be extended by users of this class to obtain call back notification of |
32 * expires. | 32 * expires. |
33 */ | 33 */ |
34 public class Timeout | 34 public class Timeout |
35 { | 35 { |
36 private static final Logger LOG = LoggerFactory.getLogger(Timeout.class); | 36 private static final Logger LOG = LoggerFactory.getLogger(Timeout.class); |
37 private Object _lock; | 37 private Object _lock; |
38 private long _duration; | 38 private long _duration; |
39 private volatile long _now=System.currentTimeMillis(); | 39 private volatile long _now=System.currentTimeMillis(); |
40 private Task _head=new Task(); | 40 private Task _head=new Task(); |
41 | 41 |
42 /* ------------------------------------------------------------ */ | 42 /* ------------------------------------------------------------ */ |
43 public Timeout() | 43 public Timeout(Object lock) |
44 { | 44 { |
45 _lock=new Object(); | 45 _lock=lock; |
46 _head._timeout=this; | 46 _head._timeout=this; |
47 } | 47 } |
48 | 48 |
49 /* ------------------------------------------------------------ */ | 49 /* ------------------------------------------------------------ */ |
50 public Timeout(Object lock) | 50 /** |
51 { | 51 * @return Returns the duration. |
52 _lock=lock; | 52 */ |
53 _head._timeout=this; | 53 public long getDuration() |
54 } | 54 { |
55 return _duration; | |
56 } | |
55 | 57 |
56 /* ------------------------------------------------------------ */ | 58 /* ------------------------------------------------------------ */ |
57 /** | 59 /** |
58 * @return Returns the duration. | 60 * @param duration The duration to set. |
59 */ | 61 */ |
60 public long getDuration() | 62 public void setDuration(long duration) |
61 { | 63 { |
62 return _duration; | 64 _duration = duration; |
63 } | 65 } |
64 | 66 |
65 /* ------------------------------------------------------------ */ | 67 /* ------------------------------------------------------------ */ |
66 /** | 68 public long setNow() |
67 * @param duration The duration to set. | 69 { |
68 */ | 70 return _now=System.currentTimeMillis(); |
69 public void setDuration(long duration) | 71 } |
70 { | 72 |
71 _duration = duration; | 73 /* ------------------------------------------------------------ */ |
72 } | 74 public long getNow() |
75 { | |
76 return _now; | |
77 } | |
73 | 78 |
74 /* ------------------------------------------------------------ */ | 79 /* ------------------------------------------------------------ */ |
75 public long setNow() | 80 public void setNow(long now) |
76 { | 81 { |
77 return _now=System.currentTimeMillis(); | 82 _now=now; |
78 } | 83 } |
79 | |
80 /* ------------------------------------------------------------ */ | |
81 public long getNow() | |
82 { | |
83 return _now; | |
84 } | |
85 | 84 |
86 /* ------------------------------------------------------------ */ | 85 /* ------------------------------------------------------------ */ |
87 public void setNow(long now) | 86 /** Get an expired tasks. |
88 { | 87 * This is called instead of {@link #tick()} to obtain the next |
89 _now=now; | 88 * expired Task, but without calling it's {@link Task#expire()} or |
90 } | 89 * {@link Task#expired()} methods. |
90 * | |
91 * @return the next expired task or null. | |
92 */ | |
91 | 93 |
92 /* ------------------------------------------------------------ */ | 94 public Task expired() |
93 /** Get an expired tasks. | 95 { |
94 * This is called instead of {@link #tick()} to obtain the next | 96 synchronized (_lock) |
95 * expired Task, but without calling it's {@link Task#expire()} or | 97 { |
96 * {@link Task#expired()} methods. | 98 long _expiry = _now-_duration; |
97 * | 99 if (_head._next!=_head) |
98 * @return the next expired task or null. | 100 { |
99 */ | 101 Task task = _head._next; |
100 public Task expired() | 102 if (task._timestamp>_expiry) |
101 { | 103 return null; |
102 synchronized (_lock) | |
103 { | |
104 long _expiry = _now-_duration; | |
105 | 104 |
106 if (_head._next!=_head) | 105 task.unlink(); |
107 { | 106 task._expired=true; |
108 Task task = _head._next; | 107 return task; |
109 if (task._timestamp>_expiry) | 108 } |
110 return null; | 109 return null; |
110 } | |
111 } | |
111 | 112 |
112 task.unlink(); | 113 public void cancelAll() |
113 task._expired=true; | 114 { |
114 return task; | 115 synchronized (_lock) |
115 } | 116 { |
116 return null; | 117 _head._next=_head._prev=_head; |
117 } | 118 } |
118 } | 119 } |
119 | 120 |
120 /* ------------------------------------------------------------ */ | 121 public long getTimeToNext() |
121 public void tick() | 122 { |
122 { | 123 synchronized (_lock) |
123 final long expiry = _now-_duration; | 124 { |
125 if (_head._next==_head) | |
126 return -1; | |
127 long to_next = _duration+_head._next._timestamp-_now; | |
128 return to_next<0?0:to_next; | |
129 } | |
130 } | |
124 | 131 |
125 Task task=null; | 132 @Override |
126 while (true) | 133 public String toString() |
127 { | 134 { |
128 try | 135 StringBuffer buf = new StringBuffer(); |
129 { | 136 buf.append(super.toString()); |
130 synchronized (_lock) | 137 |
131 { | 138 Task task = _head._next; |
132 task= _head._next; | 139 while (task!=_head) |
133 if (task==_head || task._timestamp>expiry) | 140 { |
134 break; | 141 buf.append("-->"); |
135 task.unlink(); | 142 buf.append(task); |
136 task._expired=true; | 143 task=task._next; |
137 task.expire(); | 144 } |
138 } | 145 |
139 | 146 return buf.toString(); |
140 task.expired(); | 147 } |
141 } | |
142 catch(Throwable th) | |
143 { | |
144 LOG.warn("EXCEPTION",th); | |
145 } | |
146 } | |
147 } | |
148 | 148 |
149 /* ------------------------------------------------------------ */ | 149 /* ------------------------------------------------------------ */ |
150 public void tick(long now) | 150 /* ------------------------------------------------------------ */ |
151 { | 151 /* ------------------------------------------------------------ */ |
152 _now=now; | 152 /* ------------------------------------------------------------ */ |
153 tick(); | 153 /** Task. |
154 } | 154 * The base class for scheduled timeouts. This class should be |
155 * extended to implement the expire() method, which is called if the | |
156 * timeout expires. | |
157 * | |
158 * | |
159 * | |
160 */ | |
161 public static class Task | |
162 { | |
163 Task _next; | |
164 Task _prev; | |
165 Timeout _timeout; | |
166 long _timestamp=0; | |
167 boolean _expired=false; | |
155 | 168 |
156 /* ------------------------------------------------------------ */ | 169 protected Task() |
157 public void schedule(Task task) | 170 { |
158 { | 171 _next=_prev=this; |
159 schedule(task,0L); | 172 } |
160 } | |
161 | |
162 /* ------------------------------------------------------------ */ | |
163 /** | |
164 * @param task | |
165 * @param delay A delay in addition to the default duration of the timeout | |
166 */ | |
167 public void schedule(Task task,long delay) | |
168 { | |
169 synchronized (_lock) | |
170 { | |
171 if (task._timestamp!=0) | |
172 { | |
173 task.unlink(); | |
174 task._timestamp=0; | |
175 } | |
176 task._timeout=this; | |
177 task._expired=false; | |
178 task._delay=delay; | |
179 task._timestamp = _now+delay; | |
180 | 173 |
181 Task last=_head._prev; | 174 private void unlink() |
182 while (last!=_head) | 175 { |
183 { | 176 _next._prev=_prev; |
184 if (last._timestamp <= task._timestamp) | 177 _prev._next=_next; |
185 break; | 178 _next=_prev=this; |
186 last=last._prev; | 179 _expired=false; |
187 } | 180 } |
188 last.link(task); | 181 } |
189 } | |
190 } | |
191 | |
192 | |
193 /* ------------------------------------------------------------ */ | |
194 public void cancelAll() | |
195 { | |
196 synchronized (_lock) | |
197 { | |
198 _head._next=_head._prev=_head; | |
199 } | |
200 } | |
201 | |
202 /* ------------------------------------------------------------ */ | |
203 public boolean isEmpty() | |
204 { | |
205 synchronized (_lock) | |
206 { | |
207 return _head._next==_head; | |
208 } | |
209 } | |
210 | |
211 /* ------------------------------------------------------------ */ | |
212 public long getTimeToNext() | |
213 { | |
214 synchronized (_lock) | |
215 { | |
216 if (_head._next==_head) | |
217 return -1; | |
218 long to_next = _duration+_head._next._timestamp-_now; | |
219 return to_next<0?0:to_next; | |
220 } | |
221 } | |
222 | |
223 /* ------------------------------------------------------------ */ | |
224 @Override | |
225 public String toString() | |
226 { | |
227 StringBuffer buf = new StringBuffer(); | |
228 buf.append(super.toString()); | |
229 | |
230 Task task = _head._next; | |
231 while (task!=_head) | |
232 { | |
233 buf.append("-->"); | |
234 buf.append(task); | |
235 task=task._next; | |
236 } | |
237 | |
238 return buf.toString(); | |
239 } | |
240 | |
241 /* ------------------------------------------------------------ */ | |
242 /* ------------------------------------------------------------ */ | |
243 /* ------------------------------------------------------------ */ | |
244 /* ------------------------------------------------------------ */ | |
245 /** Task. | |
246 * The base class for scheduled timeouts. This class should be | |
247 * extended to implement the expire() method, which is called if the | |
248 * timeout expires. | |
249 * | |
250 * | |
251 * | |
252 */ | |
253 public static class Task | |
254 { | |
255 Task _next; | |
256 Task _prev; | |
257 Timeout _timeout; | |
258 long _delay; | |
259 long _timestamp=0; | |
260 boolean _expired=false; | |
261 | |
262 /* ------------------------------------------------------------ */ | |
263 protected Task() | |
264 { | |
265 _next=_prev=this; | |
266 } | |
267 | |
268 /* ------------------------------------------------------------ */ | |
269 public long getTimestamp() | |
270 { | |
271 return _timestamp; | |
272 } | |
273 | |
274 /* ------------------------------------------------------------ */ | |
275 public long getAge() | |
276 { | |
277 final Timeout t = _timeout; | |
278 if (t!=null) | |
279 { | |
280 final long now=t._now; | |
281 if (now!=0 && _timestamp!=0) | |
282 return now-_timestamp; | |
283 } | |
284 return 0; | |
285 } | |
286 | |
287 /* ------------------------------------------------------------ */ | |
288 private void unlink() | |
289 { | |
290 _next._prev=_prev; | |
291 _prev._next=_next; | |
292 _next=_prev=this; | |
293 _expired=false; | |
294 } | |
295 | |
296 /* ------------------------------------------------------------ */ | |
297 private void link(Task task) | |
298 { | |
299 Task next_next = _next; | |
300 _next._prev=task; | |
301 _next=task; | |
302 _next._next=next_next; | |
303 _next._prev=this; | |
304 } | |
305 | |
306 /* ------------------------------------------------------------ */ | |
307 /** Schedule the task on the given timeout. | |
308 * The task exiry will be called after the timeout duration. | |
309 * @param timer | |
310 */ | |
311 public void schedule(Timeout timer) | |
312 { | |
313 timer.schedule(this); | |
314 } | |
315 | |
316 /* ------------------------------------------------------------ */ | |
317 /** Schedule the task on the given timeout. | |
318 * The task exiry will be called after the timeout duration. | |
319 * @param timer | |
320 */ | |
321 public void schedule(Timeout timer, long delay) | |
322 { | |
323 timer.schedule(this,delay); | |
324 } | |
325 | |
326 /* ------------------------------------------------------------ */ | |
327 /** Reschedule the task on the current timeout. | |
328 * The task timeout is rescheduled as if it had been cancelled and | |
329 * scheduled on the current timeout. | |
330 */ | |
331 public void reschedule() | |
332 { | |
333 Timeout timeout = _timeout; | |
334 if (timeout!=null) | |
335 timeout.schedule(this,_delay); | |
336 } | |
337 | |
338 /* ------------------------------------------------------------ */ | |
339 /** Cancel the task. | |
340 * Remove the task from the timeout. | |
341 */ | |
342 public void cancel() | |
343 { | |
344 Timeout timeout = _timeout; | |
345 if (timeout!=null) | |
346 { | |
347 synchronized (timeout._lock) | |
348 { | |
349 unlink(); | |
350 _timestamp=0; | |
351 } | |
352 } | |
353 } | |
354 | |
355 /* ------------------------------------------------------------ */ | |
356 public boolean isExpired() { return _expired; } | |
357 | |
358 /* ------------------------------------------------------------ */ | |
359 public boolean isScheduled() { return _next!=this; } | |
360 | |
361 /* ------------------------------------------------------------ */ | |
362 /** Expire task. | |
363 * This method is called when the timeout expires. It is called | |
364 * in the scope of the synchronize block (on this) that sets | |
365 * the {@link #isExpired()} state to true. | |
366 * @see #expired() For an unsynchronized callback. | |
367 */ | |
368 protected void expire(){} | |
369 | |
370 /* ------------------------------------------------------------ */ | |
371 /** Expire task. | |
372 * This method is called when the timeout expires. It is called | |
373 * outside of any synchronization scope and may be delayed. | |
374 * | |
375 */ | |
376 public void expired(){} | |
377 | |
378 } | |
379 | 182 |
380 } | 183 } |