View Javadoc
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   * <p>
38   * This class implements throw away objects. It is instantiated whenever
39   * a thread needs to wait. Instances are not re-used, except if the
40   * waiting thread experiences a spurious wake up and continues to wait.
41   * </p>
42   * <p>
43   * All methods assume external synchronization on the condition
44   * passed to the constructor.
45   * Instances of this class do <i>not</i> synchronize access!
46   * </p>
47   *
48   * @since 4.0
49   *
50   * @deprecated (4.2) do not use
51   */
52  @Deprecated
53  public class WaitingThread {
54  
55      /** The condition on which the thread is waiting. */
56      private final Condition cond;
57  
58      /** The route specific pool on which the thread is waiting. */
59      //@@@ replace with generic pool interface
60      private final RouteSpecificPool pool;
61  
62      /** The thread that is waiting for an entry. */
63      private Thread waiter;
64  
65      /** True if this was interrupted. */
66      private boolean aborted;
67  
68  
69      /**
70       * Creates a new entry for a waiting thread.
71       *
72       * @param cond      the condition for which to wait
73       * @param pool      the pool on which the thread will be waiting,
74       *                  or {@code null}
75       */
76      public WaitingThread(final Condition cond, final RouteSpecificPool pool) {
77  
78          Args.notNull(cond, "Condition");
79  
80          this.cond = cond;
81          this.pool = pool;
82      }
83  
84  
85      /**
86       * Obtains the condition.
87       *
88       * @return  the condition on which to wait, never {@code null}
89       */
90      public final Condition getCondition() {
91          // not synchronized
92          return this.cond;
93      }
94  
95  
96      /**
97       * Obtains the pool, if there is one.
98       *
99       * @return  the pool on which a thread is or was waiting,
100      *          or {@code null}
101      */
102     public final RouteSpecificPool getPool() {
103         // not synchronized
104         return this.pool;
105     }
106 
107 
108     /**
109      * Obtains the thread, if there is one.
110      *
111      * @return  the thread which is waiting, or {@code null}
112      */
113     public final Thread getThread() {
114         // not synchronized
115         return this.waiter;
116     }
117 
118 
119     /**
120      * Blocks the calling thread.
121      * This method returns when the thread is notified or interrupted,
122      * if a timeout occurrs, or if there is a spurious wakeup.
123      * <p>
124      * This method assumes external synchronization.
125      * </p>
126      *
127      * @param deadline  when to time out, or {@code null} for no timeout
128      *
129      * @return  {@code true} if the condition was satisfied,
130      *          {@code false} in case of a timeout.
131      *          Typically, a call to {@link #wakeup} is used to indicate
132      *          that the condition was satisfied. Since the condition is
133      *          accessible outside, this cannot be guaranteed though.
134      *
135      * @throws InterruptedException     if the waiting thread was interrupted
136      *
137      * @see #wakeup
138      */
139     public boolean await(final Date deadline)
140         throws InterruptedException {
141 
142         // This is only a sanity check. We cannot synchronize here,
143         // the lock would not be released on calling cond.await() below.
144         if (this.waiter != null) {
145             throw new IllegalStateException
146                 ("A thread is already waiting on this object." +
147                  "\ncaller: " + Thread.currentThread() +
148                  "\nwaiter: " + this.waiter);
149         }
150 
151         if (aborted) {
152             throw new InterruptedException("Operation interrupted");
153         }
154 
155         this.waiter = Thread.currentThread();
156 
157         boolean success = false;
158         try {
159             if (deadline != null) {
160                 success = this.cond.awaitUntil(deadline);
161             } else {
162                 this.cond.await();
163                 success = true;
164             }
165             if (aborted) {
166                 throw new InterruptedException("Operation interrupted");
167             }
168         } finally {
169             this.waiter = null;
170         }
171         return success;
172 
173     } // await
174 
175 
176     /**
177      * Wakes up the waiting thread.
178      * <p>
179      * This method assumes external synchronization.
180      * </p>
181      */
182     public void wakeup() {
183 
184         // If external synchronization and pooling works properly,
185         // this cannot happen. Just a sanity check.
186         if (this.waiter == null) {
187             throw new IllegalStateException
188                 ("Nobody waiting on this object.");
189         }
190 
191         // One condition might be shared by several WaitingThread instances.
192         // It probably isn't, but just in case: wake all, not just one.
193         this.cond.signalAll();
194     }
195 
196     public void interrupt() {
197         aborted = true;
198         this.cond.signalAll();
199     }
200 
201 
202 } // class WaitingThread