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