Mercurial Hosting > luan
comparison src/org/eclipse/jetty/util/thread/Timeout.java @ 802:3428c60d7cfc
replace jetty jars with source
author | Franklin Schmidt <fschmidt@gmail.com> |
---|---|
date | Wed, 07 Sep 2016 21:15:48 -0600 |
parents | |
children | 8e9db0bbf4f9 |
comparison
equal
deleted
inserted
replaced
801:6a21393191c1 | 802:3428c60d7cfc |
---|---|
1 // | |
2 // ======================================================================== | |
3 // Copyright (c) 1995-2014 Mort Bay Consulting Pty. Ltd. | |
4 // ------------------------------------------------------------------------ | |
5 // All rights reserved. This program and the accompanying materials | |
6 // are made available under the terms of the Eclipse Public License v1.0 | |
7 // and Apache License v2.0 which accompanies this distribution. | |
8 // | |
9 // The Eclipse Public License is available at | |
10 // http://www.eclipse.org/legal/epl-v10.html | |
11 // | |
12 // The Apache License v2.0 is available at | |
13 // http://www.opensource.org/licenses/apache2.0.php | |
14 // | |
15 // You may elect to redistribute this code under either of these licenses. | |
16 // ======================================================================== | |
17 // | |
18 | |
19 package org.eclipse.jetty.util.thread; | |
20 | |
21 import org.eclipse.jetty.util.log.Log; | |
22 import org.eclipse.jetty.util.log.Logger; | |
23 | |
24 | |
25 /* ------------------------------------------------------------ */ | |
26 /** Timeout queue. | |
27 * This class implements a timeout queue for timers that are at least as likely to be cancelled as they are to expire. | |
28 * Unlike the util timeout class, the duration of the timeouts is shared by all scheduled tasks and if the duration | |
29 * is changed, this affects all scheduled tasks. | |
30 * <p> | |
31 * The nested class Task should be extended by users of this class to obtain call back notification of | |
32 * expires. | |
33 */ | |
34 public class Timeout | |
35 { | |
36 private static final Logger LOG = Log.getLogger(Timeout.class); | |
37 private Object _lock; | |
38 private long _duration; | |
39 private volatile long _now=System.currentTimeMillis(); | |
40 private Task _head=new Task(); | |
41 | |
42 /* ------------------------------------------------------------ */ | |
43 public Timeout() | |
44 { | |
45 _lock=new Object(); | |
46 _head._timeout=this; | |
47 } | |
48 | |
49 /* ------------------------------------------------------------ */ | |
50 public Timeout(Object lock) | |
51 { | |
52 _lock=lock; | |
53 _head._timeout=this; | |
54 } | |
55 | |
56 /* ------------------------------------------------------------ */ | |
57 /** | |
58 * @return Returns the duration. | |
59 */ | |
60 public long getDuration() | |
61 { | |
62 return _duration; | |
63 } | |
64 | |
65 /* ------------------------------------------------------------ */ | |
66 /** | |
67 * @param duration The duration to set. | |
68 */ | |
69 public void setDuration(long duration) | |
70 { | |
71 _duration = duration; | |
72 } | |
73 | |
74 /* ------------------------------------------------------------ */ | |
75 public long setNow() | |
76 { | |
77 return _now=System.currentTimeMillis(); | |
78 } | |
79 | |
80 /* ------------------------------------------------------------ */ | |
81 public long getNow() | |
82 { | |
83 return _now; | |
84 } | |
85 | |
86 /* ------------------------------------------------------------ */ | |
87 public void setNow(long now) | |
88 { | |
89 _now=now; | |
90 } | |
91 | |
92 /* ------------------------------------------------------------ */ | |
93 /** Get an expired tasks. | |
94 * This is called instead of {@link #tick()} to obtain the next | |
95 * expired Task, but without calling it's {@link Task#expire()} or | |
96 * {@link Task#expired()} methods. | |
97 * | |
98 * @return the next expired task or null. | |
99 */ | |
100 public Task expired() | |
101 { | |
102 synchronized (_lock) | |
103 { | |
104 long _expiry = _now-_duration; | |
105 | |
106 if (_head._next!=_head) | |
107 { | |
108 Task task = _head._next; | |
109 if (task._timestamp>_expiry) | |
110 return null; | |
111 | |
112 task.unlink(); | |
113 task._expired=true; | |
114 return task; | |
115 } | |
116 return null; | |
117 } | |
118 } | |
119 | |
120 /* ------------------------------------------------------------ */ | |
121 public void tick() | |
122 { | |
123 final long expiry = _now-_duration; | |
124 | |
125 Task task=null; | |
126 while (true) | |
127 { | |
128 try | |
129 { | |
130 synchronized (_lock) | |
131 { | |
132 task= _head._next; | |
133 if (task==_head || task._timestamp>expiry) | |
134 break; | |
135 task.unlink(); | |
136 task._expired=true; | |
137 task.expire(); | |
138 } | |
139 | |
140 task.expired(); | |
141 } | |
142 catch(Throwable th) | |
143 { | |
144 LOG.warn(Log.EXCEPTION,th); | |
145 } | |
146 } | |
147 } | |
148 | |
149 /* ------------------------------------------------------------ */ | |
150 public void tick(long now) | |
151 { | |
152 _now=now; | |
153 tick(); | |
154 } | |
155 | |
156 /* ------------------------------------------------------------ */ | |
157 public void schedule(Task task) | |
158 { | |
159 schedule(task,0L); | |
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 | |
181 Task last=_head._prev; | |
182 while (last!=_head) | |
183 { | |
184 if (last._timestamp <= task._timestamp) | |
185 break; | |
186 last=last._prev; | |
187 } | |
188 last.link(task); | |
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 | |
380 } |