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