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