| /* |
| * $HeadURL: http://svn.apache.org/repos/asf/httpcomponents/httpclient/trunk/module-client/src/main/java/org/apache/http/impl/conn/tsccm/WaitingThread.java $ |
| * $Revision: 649217 $ |
| * $Date: 2008-04-17 11:32:32 -0700 (Thu, 17 Apr 2008) $ |
| * |
| * ==================================================================== |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| * ==================================================================== |
| * |
| * This software consists of voluntary contributions made by many |
| * individuals on behalf of the Apache Software Foundation. For more |
| * information on the Apache Software Foundation, please see |
| * <http://www.apache.org/>. |
| * |
| */ |
| |
| package org.apache.http.impl.conn.tsccm; |
| |
| |
| import java.util.Date; |
| import java.util.concurrent.locks.Condition; |
| |
| |
| /** |
| * Represents a thread waiting for a connection. |
| * This class implements throwaway objects. It is instantiated whenever |
| * a thread needs to wait. Instances are not re-used, except if the |
| * waiting thread experiences a spurious wakeup and continues to wait. |
| * <br/> |
| * All methods assume external synchronization on the condition |
| * passed to the constructor. |
| * Instances of this class do <i>not</i> synchronize access! |
| * |
| * @author <a href="mailto:rolandw at apache.org">Roland Weber</a> |
| */ |
| public class WaitingThread { |
| |
| /** The condition on which the thread is waiting. */ |
| private final Condition cond; |
| |
| /** The route specific pool on which the thread is waiting. */ |
| //@@@ replace with generic pool interface |
| private final RouteSpecificPool pool; |
| |
| /** The thread that is waiting for an entry. */ |
| private Thread waiter; |
| |
| /** True if this was interrupted. */ |
| private boolean aborted; |
| |
| |
| /** |
| * Creates a new entry for a waiting thread. |
| * |
| * @param cond the condition for which to wait |
| * @param pool the pool on which the thread will be waiting, |
| * or <code>null</code> |
| */ |
| public WaitingThread(Condition cond, RouteSpecificPool pool) { |
| |
| if (cond == null) { |
| throw new IllegalArgumentException("Condition must not be null."); |
| } |
| |
| this.cond = cond; |
| this.pool = pool; |
| } |
| |
| |
| /** |
| * Obtains the condition. |
| * |
| * @return the condition on which to wait, never <code>null</code> |
| */ |
| public final Condition getCondition() { |
| // not synchronized |
| return this.cond; |
| } |
| |
| |
| /** |
| * Obtains the pool, if there is one. |
| * |
| * @return the pool on which a thread is or was waiting, |
| * or <code>null</code> |
| */ |
| public final RouteSpecificPool getPool() { |
| // not synchronized |
| return this.pool; |
| } |
| |
| |
| /** |
| * Obtains the thread, if there is one. |
| * |
| * @return the thread which is waiting, or <code>null</code> |
| */ |
| public final Thread getThread() { |
| // not synchronized |
| return this.waiter; |
| } |
| |
| |
| /** |
| * Blocks the calling thread. |
| * This method returns when the thread is notified or interrupted, |
| * if a timeout occurrs, or if there is a spurious wakeup. |
| * <br/> |
| * This method assumes external synchronization. |
| * |
| * @param deadline when to time out, or <code>null</code> for no timeout |
| * |
| * @return <code>true</code> if the condition was satisfied, |
| * <code>false</code> in case of a timeout. |
| * Typically, a call to {@link #wakeup} is used to indicate |
| * that the condition was satisfied. Since the condition is |
| * accessible outside, this cannot be guaranteed though. |
| * |
| * @throws InterruptedException if the waiting thread was interrupted |
| * |
| * @see #wakeup |
| */ |
| public boolean await(Date deadline) |
| throws InterruptedException { |
| |
| // This is only a sanity check. We cannot synchronize here, |
| // the lock would not be released on calling cond.await() below. |
| if (this.waiter != null) { |
| throw new IllegalStateException |
| ("A thread is already waiting on this object." + |
| "\ncaller: " + Thread.currentThread() + |
| "\nwaiter: " + this.waiter); |
| } |
| |
| if (aborted) |
| throw new InterruptedException("Operation interrupted"); |
| |
| this.waiter = Thread.currentThread(); |
| |
| boolean success = false; |
| try { |
| if (deadline != null) { |
| success = this.cond.awaitUntil(deadline); |
| } else { |
| this.cond.await(); |
| success = true; |
| } |
| if (aborted) |
| throw new InterruptedException("Operation interrupted"); |
| } finally { |
| this.waiter = null; |
| } |
| return success; |
| |
| } // await |
| |
| |
| /** |
| * Wakes up the waiting thread. |
| * <br/> |
| * This method assumes external synchronization. |
| */ |
| public void wakeup() { |
| |
| // If external synchronization and pooling works properly, |
| // this cannot happen. Just a sanity check. |
| if (this.waiter == null) { |
| throw new IllegalStateException |
| ("Nobody waiting on this object."); |
| } |
| |
| // One condition might be shared by several WaitingThread instances. |
| // It probably isn't, but just in case: wake all, not just one. |
| this.cond.signalAll(); |
| } |
| |
| public void interrupt() { |
| aborted = true; |
| this.cond.signalAll(); |
| } |
| |
| |
| } // class WaitingThread |