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