comparison src/ch/ethz/ssh2/util/TimeoutService.java @ 273:91a31873c42a ganymed

start conversion from trilead to ganymed
author Carl Byington <carl@five-ten-sg.com>
date Fri, 18 Jul 2014 11:21:46 -0700
parents
children 071eccdff8ea
comparison
equal deleted inserted replaced
272:ce2f4e397703 273:91a31873c42a
1 /*
2 * Copyright (c) 2006-2011 Christian Plattner. All rights reserved.
3 * Please refer to the LICENSE.txt for licensing details.
4 */
5
6 package ch.ethz.ssh2.util;
7
8 import java.io.PrintWriter;
9 import java.io.StringWriter;
10 import java.util.Collections;
11 import java.util.Comparator;
12 import java.util.LinkedList;
13
14 import ch.ethz.ssh2.log.Logger;
15
16 /**
17 * TimeoutService (beta). Here you can register a timeout.
18 * <p>
19 * Implemented having large scale programs in mind: if you open many concurrent SSH connections
20 * that rely on timeouts, then there will be only one timeout thread. Once all timeouts
21 * have expired/are cancelled, the thread will (sooner or later) exit.
22 * Only after new timeouts arrive a new thread (singleton) will be instantiated.
23 *
24 * @author Christian Plattner
25 * @version $Id: TimeoutService.java 89 2014-04-07 14:36:24Z dkocher@sudo.ch $
26 */
27 public class TimeoutService
28 {
29 private static final Logger log = Logger.getLogger(TimeoutService.class);
30
31 public static class TimeoutToken
32 {
33 private long runTime;
34 private Runnable handler;
35
36 private TimeoutToken(long runTime, Runnable handler)
37 {
38 this.runTime = runTime;
39 this.handler = handler;
40 }
41 }
42
43 private static class TimeoutThread extends Thread
44 {
45 @Override
46 public void run()
47 {
48 synchronized (todolist)
49 {
50 while (true)
51 {
52 if (todolist.size() == 0)
53 {
54 timeoutThread = null;
55 return;
56 }
57
58 long now = System.currentTimeMillis();
59
60 TimeoutToken tt = todolist.getFirst();
61
62 if (tt.runTime > now)
63 {
64 /* Not ready yet, sleep a little bit */
65
66 try
67 {
68 todolist.wait(tt.runTime - now);
69 }
70 catch (InterruptedException ignored)
71 {
72 }
73
74 /* We cannot simply go on, since it could be that the token
75 * was removed (cancelled) or another one has been inserted in
76 * the meantime.
77 */
78
79 continue;
80 }
81
82 todolist.removeFirst();
83
84 try
85 {
86 tt.handler.run();
87 }
88 catch (Exception e)
89 {
90 StringWriter sw = new StringWriter();
91 e.printStackTrace(new PrintWriter(sw));
92 log.warning("Exeception in Timeout handler:" + e.getMessage() + "(" + sw.toString() + ")");
93 }
94 }
95 }
96 }
97 }
98
99 /* The list object is also used for locking purposes */
100 private static final LinkedList<TimeoutToken> todolist = new LinkedList<TimeoutService.TimeoutToken>();
101
102 private static Thread timeoutThread = null;
103
104 /**
105 * It is assumed that the passed handler will not execute for a long time.
106 *
107 * @param runTime
108 * @param handler
109 * @return a TimeoutToken that can be used to cancel the timeout.
110 */
111 public static TimeoutToken addTimeoutHandler(long runTime, Runnable handler)
112 {
113 TimeoutToken token = new TimeoutToken(runTime, handler);
114
115 synchronized (todolist)
116 {
117 todolist.add(token);
118
119 Collections.sort(todolist, new Comparator<TimeoutToken>()
120 {
121 public int compare(TimeoutToken o1, TimeoutToken o2)
122 {
123 if (o1.runTime > o2.runTime)
124 return 1;
125 if (o1.runTime == o2.runTime)
126 return 0;
127 return -1;
128 }
129 });
130
131 if (timeoutThread != null)
132 timeoutThread.interrupt();
133 else
134 {
135 timeoutThread = new TimeoutThread();
136 timeoutThread.setDaemon(true);
137 timeoutThread.start();
138 }
139 }
140
141 return token;
142 }
143
144 public static void cancelTimeoutHandler(TimeoutToken token)
145 {
146 synchronized (todolist)
147 {
148 todolist.remove(token);
149
150 if (timeoutThread != null)
151 timeoutThread.interrupt();
152 }
153 }
154
155 }