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 ch.boye.httpclientandroidlib.impl.conn.tsccm;
28 
29 
30 import java.util.Date;
31 import java.util.concurrent.locks.Condition;
32 
33 import ch.boye.httpclientandroidlib.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      */
WaitingThread(final Condition cond, final RouteSpecificPool pool)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      */
getCondition()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      */
getPool()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      */
getThread()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      */
await(final Date deadline)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      */
wakeup()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 
interrupt()192     public void interrupt() {
193         aborted = true;
194         this.cond.signalAll();
195     }
196 
197 
198 } // class WaitingThread
199