/*
 * Copyright 2000-2006 Sun Microsystems, Inc.  All Rights Reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Sun designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Sun in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
 * CA 95054 USA or visit www.sun.com if you need additional information or
 * have any questions.
 */

package sun.awt;

import java.awt.AWTEvent;
import java.util.Collections;
import java.util.HashSet;
import java.util.IdentityHashMap;
import java.util.Map;
import java.util.logging.Logger;

/**
 * This class is to let AWT shutdown automatically when a user is done
 * with AWT. It tracks AWT state using the following parameters:
 * <ul>
 * <li><code>peerMap</code> - the map between the existing peer objects
 *     and their associated targets
 * <li><code>toolkitThreadBusy</code> - whether the toolkit thread
 *     is waiting for a new native event to appear in its queue
 *     or is dispatching an event
 * <li><code>busyThreadSet</code> - a set of all the event dispatch
 *     threads that are busy at this moment, i.e. those that are not
 *     waiting for a new event to appear in their event queue.
 * </ul><p>
 * AWT is considered to be in ready-to-shutdown state when
 * <code>peerMap</code> is empty and <code>toolkitThreadBusy</code>
 * is false and <code>busyThreadSet</code> is empty.
 * The internal AWTAutoShutdown logic secures that the single non-daemon
 * thread (<code>blockerThread</code>) is running when AWT is not in
 * ready-to-shutdown state. This blocker thread is to prevent AWT from
 * exiting since the toolkit thread is now daemon and all the event
 * dispatch threads are started only when needed. Once it is detected
 * that AWT is in ready-to-shutdown state this blocker thread waits
 * for a certain timeout and if AWT state doesn't change during timeout
 * this blocker thread terminates all the event dispatch threads and
 * exits.
 */
public final class AWTAutoShutdown implements Runnable {

    private static final AWTAutoShutdown theInstance = new AWTAutoShutdown();

    /**
     * This lock object is used to synchronize shutdown operations.
     */
    private final Object mainLock = new Object();

    /**
     * This lock object is to secure that when a new blocker thread is
     * started it will be the first who acquire the main lock after
     * the thread that created the new blocker released the main lock
     * by calling lock.wait() to wait for the blocker to start.
     */
    private final Object activationLock = new Object();

    /**
     * This set keeps references to all the event dispatch threads that
     * are busy at this moment, i.e. those that are not waiting for a
     * new event to appear in their event queue.
     * Access is synchronized on the main lock object.
     */
    private final HashSet busyThreadSet = new HashSet(7);

    /**
     * Indicates whether the toolkit thread is waiting for a new native
     * event to appear or is dispatching an event.
     */
    private boolean toolkitThreadBusy = false;

    /**
     * This is a map between components and their peers.
     * we should work with in under activationLock&mainLock lock.
     */
    private final Map peerMap = new IdentityHashMap();

    /**
     * References the alive non-daemon thread that is currently used
     * for keeping AWT from exiting.
     */
    private Thread blockerThread = null;

    /**
     * We need this flag to secure that AWT state hasn't changed while
     * we were waiting for the safety timeout to pass.
     */
    private boolean timeoutPassed = false;

    /**
     * Once we detect that AWT is ready to shutdown we wait for a certain
     * timeout to pass before stopping event dispatch threads.
     */
    private static final int SAFETY_TIMEOUT = 1000;

    /**
     * Constructor method is intentionally made private to secure
     * a single instance. Use getInstance() to reference it.
     *
     * @see     AWTAutoShutdown#getInstance
     */
    private AWTAutoShutdown() {}

    /**
     * Returns reference to a single AWTAutoShutdown instance.
     */
    public static AWTAutoShutdown getInstance() {
        return theInstance;
    }

    /**
     * Notify that the toolkit thread is not waiting for a native event
     * to appear in its queue.
     *
     * @see     AWTAutoShutdown#notifyToolkitThreadFree
     * @see     AWTAutoShutdown#setToolkitBusy
     * @see     AWTAutoShutdown#isReadyToShutdown
     */
    public static void notifyToolkitThreadBusy() {
        getInstance().setToolkitBusy(true);
    }

    /**
     * Notify that the toolkit thread is waiting for a native event
     * to appear in its queue.
     *
     * @see     AWTAutoShutdown#notifyToolkitThreadFree
     * @see     AWTAutoShutdown#setToolkitBusy
     * @see     AWTAutoShutdown#isReadyToShutdown
     */
    public static void notifyToolkitThreadFree() {
        getInstance().setToolkitBusy(false);
    }

    /**
     * Add a specified thread to the set of busy event dispatch threads.
     * If this set already contains the specified thread, the call leaves
     * this set unchanged and returns silently.
     *
     * @param thread thread to be added to this set, if not present.
     * @see     AWTAutoShutdown#notifyThreadFree
     * @see     AWTAutoShutdown#isReadyToShutdown
     */
    public void notifyThreadBusy(final Thread thread) {
        synchronized (activationLock) {
            synchronized (mainLock) {
                if (blockerThread == null) {
                    activateBlockerThread();
                } else if (isReadyToShutdown()) {
                    mainLock.notifyAll();
                    timeoutPassed = false;
                }
                busyThreadSet.add(thread);
            }
        }
    }

    /**
     * Remove a specified thread from the set of busy event dispatch threads.
     * If this set doesn't contain the specified thread, the call leaves
     * this set unchanged and returns silently.
     *
     * @param thread thread to be removed from this set, if present.
     * @see     AWTAutoShutdown#notifyThreadBusy
     * @see     AWTAutoShutdown#isReadyToShutdown
     */
    public void notifyThreadFree(final Thread thread) {
        synchronized (activationLock) {
            synchronized (mainLock) {
                busyThreadSet.remove(thread);
                if (isReadyToShutdown()) {
                    mainLock.notifyAll();
                    timeoutPassed = false;
                }
            }
        }
    }

    /**
     * Notify that the peermap has been updated, that means a new peer
     * has been created or some existing peer has been disposed.
     *
     * @see     AWTAutoShutdown#isReadyToShutdown
     */
    void notifyPeerMapUpdated() {
        synchronized (activationLock) {
            synchronized (mainLock) {
                if (!isReadyToShutdown() && blockerThread == null) {
                    activateBlockerThread();
                } else {
                    mainLock.notifyAll();
                    timeoutPassed = false;
                }
            }
        }
    }

    /**
     * Determine whether AWT is currently in ready-to-shutdown state.
     * AWT is considered to be in ready-to-shutdown state if
     * <code>peerMap</code> is empty and <code>toolkitThreadBusy</code>
     * is false and <code>busyThreadSet</code> is empty.
     *
     * @return true if AWT is in ready-to-shutdown state.
     */
    private boolean isReadyToShutdown() {
        return (!toolkitThreadBusy &&
                 peerMap.isEmpty() &&
                 busyThreadSet.isEmpty());
    }

    /**
     * Notify about the toolkit thread state change.
     *
     * @param busy true if the toolkit thread state changes from idle
     *             to busy.
     * @see     AWTAutoShutdown#notifyToolkitThreadBusy
     * @see     AWTAutoShutdown#notifyToolkitThreadFree
     * @see     AWTAutoShutdown#isReadyToShutdown
     */
    private void setToolkitBusy(final boolean busy) {
        if (busy != toolkitThreadBusy) {
            synchronized (activationLock) {
                synchronized (mainLock) {
                    if (busy != toolkitThreadBusy) {
                        if (busy) {
                            if (blockerThread == null) {
                                activateBlockerThread();
                            } else if (isReadyToShutdown()) {
                                mainLock.notifyAll();
                                timeoutPassed = false;
                            }
                            toolkitThreadBusy = busy;
                        } else {
                            toolkitThreadBusy = busy;
                            if (isReadyToShutdown()) {
                                mainLock.notifyAll();
                                timeoutPassed = false;
                            }
                        }
                    }
                }
            }
        }
    }

    /**
     * Implementation of the Runnable interface.
     * Incapsulates the blocker thread functionality.
     *
     * @see     AWTAutoShutdown#isReadyToShutdown
     */
    public void run() {
        Thread currentThread = Thread.currentThread();
        boolean interrupted = false;
        synchronized (mainLock) {
            try {
                /* Notify that the thread is started. */
                mainLock.notifyAll();
                while (blockerThread == currentThread) {
                    mainLock.wait();
                    timeoutPassed = false;
                    /*
                     * This loop is introduced to handle the following case:
                     * it is possible that while we are waiting for the
                     * safety timeout to pass AWT state can change to
                     * not-ready-to-shutdown and back to ready-to-shutdown.
                     * In this case we have to wait once again.
                     * NOTE: we shouldn't break into the outer loop
                     * in this case, since we may never be notified
                     * in an outer infinite wait at this point.
                     */
                    while (isReadyToShutdown()) {
                        if (timeoutPassed) {
                            timeoutPassed = false;
                            blockerThread = null;
                            break;
                        }
                        timeoutPassed = true;
                        mainLock.wait(SAFETY_TIMEOUT);
                    }
                }
            } catch (InterruptedException e) {
                interrupted = true;
            } finally {
                if (blockerThread == currentThread) {
                    blockerThread = null;
                }
            }
        }
        if (!interrupted) {
            AppContext.stopEventDispatchThreads();
        }
    }

    static AWTEvent getShutdownEvent() {
        return new AWTEvent(getInstance(), 0) {};
    }

    /**
     * Creates and starts a new blocker thread. Doesn't return until
     * the new blocker thread starts.
     */
    private void activateBlockerThread() {
        Thread thread = new Thread(this, "AWT-Shutdown");
        thread.setDaemon(false);
        blockerThread = thread;
        thread.start();
        try {
            /* Wait for the blocker thread to start. */
            mainLock.wait();
        } catch (InterruptedException e) {
            System.err.println("AWT blocker activation interrupted:");
            e.printStackTrace();
        }
    }

    final void registerPeer(final Object target, final Object peer) {
        synchronized (activationLock) {
            synchronized (mainLock) {
                peerMap.put(target, peer);
                notifyPeerMapUpdated();
            }
        }
    }

    final void unregisterPeer(final Object target, final Object peer) {
        synchronized (activationLock) {
            synchronized (mainLock) {
                if (peerMap.get(target) == peer) {
                    peerMap.remove(target);
                    notifyPeerMapUpdated();
                }
            }
        }
    }

    final Object getPeer(final Object target) {
        synchronized (activationLock) {
            synchronized (mainLock) {
                return peerMap.get(target);
            }
        }
    }

    final void dumpPeers(final Logger aLog) {
        synchronized (activationLock) {
            synchronized (mainLock) {
                aLog.fine("Mapped peers:");
                for (Object key : peerMap.keySet()) {
                    aLog.fine(key + "->" + peerMap.get(key));
                }
            }
        }
    }

} // class AWTAutoShutdown
