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   * 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