comparison app/src/main/java/ch/ethz/ssh2/util/TimeoutService.java @ 438:d29cce60f393

migrate from Eclipse to Android Studio
author Carl Byington <carl@five-ten-sg.com>
date Thu, 03 Dec 2015 11:23:55 -0800
parents src/ch/ethz/ssh2/util/TimeoutService.java@071eccdff8ea
children
comparison
equal deleted inserted replaced
437:208b31032318 438:d29cce60f393
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 private static final Logger log = Logger.getLogger(TimeoutService.class);
29
30 public static class TimeoutToken {
31 private long runTime;
32 private Runnable handler;
33
34 private TimeoutToken(long runTime, Runnable handler) {
35 this.runTime = runTime;
36 this.handler = handler;
37 }
38 }
39
40 private static class TimeoutThread extends Thread {
41 @Override
42 public void run() {
43 synchronized (todolist) {
44 while (true) {
45 if (todolist.size() == 0) {
46 timeoutThread = null;
47 return;
48 }
49
50 long now = System.currentTimeMillis();
51 TimeoutToken tt = todolist.getFirst();
52
53 if (tt.runTime > now) {
54 /* Not ready yet, sleep a little bit */
55 try {
56 todolist.wait(tt.runTime - now);
57 }
58 catch (InterruptedException ignored) {
59 }
60
61 /* We cannot simply go on, since it could be that the token
62 * was removed (cancelled) or another one has been inserted in
63 * the meantime.
64 */
65 continue;
66 }
67
68 todolist.removeFirst();
69
70 try {
71 tt.handler.run();
72 }
73 catch (Exception e) {
74 StringWriter sw = new StringWriter();
75 e.printStackTrace(new PrintWriter(sw));
76 log.warning("Exeception in Timeout handler:" + e.getMessage() + "(" + sw.toString() + ")");
77 }
78 }
79 }
80 }
81 }
82
83 /* The list object is also used for locking purposes */
84 private static final LinkedList<TimeoutToken> todolist = new LinkedList<TimeoutService.TimeoutToken>();
85
86 private static Thread timeoutThread = null;
87
88 /**
89 * It is assumed that the passed handler will not execute for a long time.
90 *
91 * @param runTime
92 * @param handler
93 * @return a TimeoutToken that can be used to cancel the timeout.
94 */
95 public static TimeoutToken addTimeoutHandler(long runTime, Runnable handler) {
96 TimeoutToken token = new TimeoutToken(runTime, handler);
97
98 synchronized (todolist) {
99 todolist.add(token);
100 Collections.sort(todolist, new Comparator<TimeoutToken>() {
101 public int compare(TimeoutToken o1, TimeoutToken o2) {
102 if (o1.runTime > o2.runTime)
103 return 1;
104
105 if (o1.runTime == o2.runTime)
106 return 0;
107
108 return -1;
109 }
110 });
111
112 if (timeoutThread != null)
113 timeoutThread.interrupt();
114 else {
115 timeoutThread = new TimeoutThread();
116 timeoutThread.setDaemon(true);
117 timeoutThread.start();
118 }
119 }
120
121 return token;
122 }
123
124 public static void cancelTimeoutHandler(TimeoutToken token) {
125 synchronized (todolist) {
126 todolist.remove(token);
127
128 if (timeoutThread != null)
129 timeoutThread.interrupt();
130 }
131 }
132
133 }