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