1 /*
2 * ====================================================================
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 * ====================================================================
20 *
21 * This software consists of voluntary contributions made by many
22 * individuals on behalf of the Apache Software Foundation. For more
23 * information on the Apache Software Foundation, please see
24 * <http://www.apache.org/>.
25 *
26 */
27 package org.apache.http.impl.conn.tsccm;
28
29
30 import java.util.Date;
31 import java.util.concurrent.locks.Condition;
32
33 import org.apache.http.util.Args;
34
35 /**
36 * Represents a thread waiting for a connection.
37 * This class implements throwaway objects. It is instantiated whenever
38 * a thread needs to wait. Instances are not re-used, except if the
39 * waiting thread experiences a spurious wakeup and continues to wait.
40 * <br/>
41 * All methods assume external synchronization on the condition
42 * passed to the constructor.
43 * Instances of this class do <i>not</i> synchronize access!
44 *
45 *
46 * @since 4.0
47 *
48 * @deprecated (4.2) do not use
49 */
50 @Deprecated
51 public class WaitingThread {
52
53 /** The condition on which the thread is waiting. */
54 private final Condition cond;
55
56 /** The route specific pool on which the thread is waiting. */
57 //@@@ replace with generic pool interface
58 private final RouteSpecificPool pool;
59
60 /** The thread that is waiting for an entry. */
61 private Thread waiter;
62
63 /** True if this was interrupted. */
64 private boolean aborted;
65
66
67 /**
68 * Creates a new entry for a waiting thread.
69 *
70 * @param cond the condition for which to wait
71 * @param pool the pool on which the thread will be waiting,
72 * or <code>null</code>
73 */
74 public WaitingThread(final Condition cond, final RouteSpecificPool pool) {
75
76 Args.notNull(cond, "Condition");
77
78 this.cond = cond;
79 this.pool = pool;
80 }
81
82
83 /**
84 * Obtains the condition.
85 *
86 * @return the condition on which to wait, never <code>null</code>
87 */
88 public final Condition getCondition() {
89 // not synchronized
90 return this.cond;
91 }
92
93
94 /**
95 * Obtains the pool, if there is one.
96 *
97 * @return the pool on which a thread is or was waiting,
98 * or <code>null</code>
99 */
100 public final RouteSpecificPool getPool() {
101 // not synchronized
102 return this.pool;
103 }
104
105
106 /**
107 * Obtains the thread, if there is one.
108 *
109 * @return the thread which is waiting, or <code>null</code>
110 */
111 public final Thread getThread() {
112 // not synchronized
113 return this.waiter;
114 }
115
116
117 /**
118 * Blocks the calling thread.
119 * This method returns when the thread is notified or interrupted,
120 * if a timeout occurrs, or if there is a spurious wakeup.
121 * <br/>
122 * This method assumes external synchronization.
123 *
124 * @param deadline when to time out, or <code>null</code> for no timeout
125 *
126 * @return <code>true</code> if the condition was satisfied,
127 * <code>false</code> in case of a timeout.
128 * Typically, a call to {@link #wakeup} is used to indicate
129 * that the condition was satisfied. Since the condition is
130 * accessible outside, this cannot be guaranteed though.
131 *
132 * @throws InterruptedException if the waiting thread was interrupted
133 *
134 * @see #wakeup
135 */
136 public boolean await(final Date deadline)
137 throws InterruptedException {
138
139 // This is only a sanity check. We cannot synchronize here,
140 // the lock would not be released on calling cond.await() below.
141 if (this.waiter != null) {
142 throw new IllegalStateException
143 ("A thread is already waiting on this object." +
144 "\ncaller: " + Thread.currentThread() +
145 "\nwaiter: " + this.waiter);
146 }
147
148 if (aborted) {
149 throw new InterruptedException("Operation interrupted");
150 }
151
152 this.waiter = Thread.currentThread();
153
154 boolean success = false;
155 try {
156 if (deadline != null) {
157 success = this.cond.awaitUntil(deadline);
158 } else {
159 this.cond.await();
160 success = true;
161 }
162 if (aborted) {
163 throw new InterruptedException("Operation interrupted");
164 }
165 } finally {
166 this.waiter = null;
167 }
168 return success;
169
170 } // await
171
172
173 /**
174 * Wakes up the waiting thread.
175 * <br/>
176 * This method assumes external synchronization.
177 */
178 public void wakeup() {
179
180 // If external synchronization and pooling works properly,
181 // this cannot happen. Just a sanity check.
182 if (this.waiter == null) {
183 throw new IllegalStateException
184 ("Nobody waiting on this object.");
185 }
186
187 // One condition might be shared by several WaitingThread instances.
188 // It probably isn't, but just in case: wake all, not just one.
189 this.cond.signalAll();
190 }
191
192 public void interrupt() {
193 aborted = true;
194 this.cond.signalAll();
195 }
196
197
198 } // class WaitingThread