Mercurial > 510Connectbot
comparison src/com/trilead/ssh2/util/TimeoutService.java @ 0:0ce5cc452d02
initial version
author | Carl Byington <carl@five-ten-sg.com> |
---|---|
date | Thu, 22 May 2014 10:41:19 -0700 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:0ce5cc452d02 |
---|---|
1 | |
2 package com.trilead.ssh2.util; | |
3 | |
4 import java.io.PrintWriter; | |
5 import java.io.StringWriter; | |
6 import java.util.Collections; | |
7 import java.util.LinkedList; | |
8 | |
9 import com.trilead.ssh2.log.Logger; | |
10 | |
11 | |
12 /** | |
13 * TimeoutService (beta). Here you can register a timeout. | |
14 * <p> | |
15 * Implemented having large scale programs in mind: if you open many concurrent SSH connections | |
16 * that rely on timeouts, then there will be only one timeout thread. Once all timeouts | |
17 * have expired/are cancelled, the thread will (sooner or later) exit. | |
18 * Only after new timeouts arrive a new thread (singleton) will be instantiated. | |
19 * | |
20 * @author Christian Plattner, plattner@trilead.com | |
21 * @version $Id: TimeoutService.java,v 1.1 2007/10/15 12:49:57 cplattne Exp $ | |
22 */ | |
23 public class TimeoutService { | |
24 private static final Logger log = Logger.getLogger(TimeoutService.class); | |
25 | |
26 public static class TimeoutToken implements Comparable { | |
27 private long runTime; | |
28 private Runnable handler; | |
29 | |
30 private TimeoutToken(long runTime, Runnable handler) { | |
31 this.runTime = runTime; | |
32 this.handler = handler; | |
33 } | |
34 | |
35 public int compareTo(Object o) { | |
36 TimeoutToken t = (TimeoutToken) o; | |
37 | |
38 if (runTime > t.runTime) | |
39 return 1; | |
40 | |
41 if (runTime == t.runTime) | |
42 return 0; | |
43 | |
44 return -1; | |
45 } | |
46 } | |
47 | |
48 private static class TimeoutThread extends Thread { | |
49 public void run() { | |
50 synchronized (todolist) { | |
51 while (true) { | |
52 if (todolist.size() == 0) { | |
53 timeoutThread = null; | |
54 return; | |
55 } | |
56 | |
57 long now = System.currentTimeMillis(); | |
58 TimeoutToken tt = (TimeoutToken) todolist.getFirst(); | |
59 | |
60 if (tt.runTime > now) { | |
61 /* Not ready yet, sleep a little bit */ | |
62 try { | |
63 todolist.wait(tt.runTime - now); | |
64 } | |
65 catch (InterruptedException e) { | |
66 } | |
67 | |
68 /* We cannot simply go on, since it could be that the token | |
69 * was removed (cancelled) or another one has been inserted in | |
70 * the meantime. | |
71 */ | |
72 continue; | |
73 } | |
74 | |
75 todolist.removeFirst(); | |
76 | |
77 try { | |
78 tt.handler.run(); | |
79 } | |
80 catch (Exception e) { | |
81 StringWriter sw = new StringWriter(); | |
82 e.printStackTrace(new PrintWriter(sw)); | |
83 log.log(20, "Exeception in Timeout handler:" + e.getMessage() + "(" + sw.toString() + ")"); | |
84 } | |
85 } | |
86 } | |
87 } | |
88 } | |
89 | |
90 /* The list object is also used for locking purposes */ | |
91 private static final LinkedList todolist = new LinkedList(); | |
92 | |
93 private static Thread timeoutThread = null; | |
94 | |
95 /** | |
96 * It is assumed that the passed handler will not execute for a long time. | |
97 * | |
98 * @param runTime | |
99 * @param handler | |
100 * @return a TimeoutToken that can be used to cancel the timeout. | |
101 */ | |
102 public static final TimeoutToken addTimeoutHandler(long runTime, Runnable handler) { | |
103 TimeoutToken token = new TimeoutToken(runTime, handler); | |
104 | |
105 synchronized (todolist) { | |
106 todolist.add(token); | |
107 Collections.sort(todolist); | |
108 | |
109 if (timeoutThread != null) | |
110 timeoutThread.interrupt(); | |
111 else { | |
112 timeoutThread = new TimeoutThread(); | |
113 timeoutThread.setDaemon(true); | |
114 timeoutThread.start(); | |
115 } | |
116 } | |
117 | |
118 return token; | |
119 } | |
120 | |
121 public static final void cancelTimeoutHandler(TimeoutToken token) { | |
122 synchronized (todolist) { | |
123 todolist.remove(token); | |
124 | |
125 if (timeoutThread != null) | |
126 timeoutThread.interrupt(); | |
127 } | |
128 } | |
129 | |
130 } |