/*
 * Copyright 1998-2005 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 com.sun.jdi.event;

import com.sun.jdi.*;

import java.util.Set;

/**
 * Several {@link Event} objects may be created at a given time by
 * the target {@link VirtualMachine}. For example, there may be
 * more than one {@link com.sun.jdi.request.BreakpointRequest}
 * for a given {@link Location}
 * or you might single step to the same location as a
 * BreakpointRequest.  These {@link Event} objects are delivered
 * together as an EventSet.  For uniformity, an EventSet is always used
 * to deliver {@link Event} objects.  EventSets are delivered by
 * the {@link EventQueue}.
 * EventSets are unmodifiable.
 * <P>
 * Associated with the issuance of an event set, suspensions may
 * have occurred in the target VM.  These suspensions correspond
 * with the {@link #suspendPolicy() suspend policy}.
 * To assure matching resumes occur, it is recommended,
 * where possible,
 * to complete the processing of an event set with
 * {@link #resume() EventSet.resume()}.
 * <P>
 * The events that are grouped in an EventSet are restricted in the
 * following ways:
 * <P>
 * <UL>
 * <LI>Always singleton sets:
 *     <UL>
 *     <LI>{@link VMStartEvent}
 *     <LI>{@link VMDisconnectEvent}
 *     </UL>
 * <LI>Only with other VMDeathEvents:
 *     <UL>
 *     <LI>{@link VMDeathEvent}
 *     </UL>
 * <LI>Only with other ThreadStartEvents for the same thread:
 *     <UL>
 *     <LI>{@link ThreadStartEvent}
 *     </UL>
 * <LI>Only with other ThreadDeathEvents for the same thread:
 *     <UL>
 *     <LI>{@link ThreadDeathEvent}
 *     </UL>
 * <LI>Only with other ClassPrepareEvents for the same class:
 *     <UL>
 *     <LI>{@link ClassPrepareEvent}
 *     </UL>
 * <LI>Only with other ClassUnloadEvents for the same class:
 *     <UL>
 *     <LI>{@link ClassUnloadEvent}
 *     </UL>
 * <LI>Only with other AccessWatchpointEvents for the same field access:
 *     <UL>
 *     <LI>{@link AccessWatchpointEvent}
 *     </UL>
 * <LI>Only with other ModificationWatchpointEvents for the same field
 * modification:
 *     <UL>
 *     <LI>{@link ModificationWatchpointEvent}
 *     </UL>
 * <LI>Only with other ExceptionEvents for the same exception occurrance:
 *     <UL>
 *     <LI>{@link ExceptionEvent}
 *     </UL>
 * <LI>Only with other MethodExitEvents for the same method exit:
 *     <UL>
 *     <LI>{@link MethodExitEvent}
 *     </UL>
 * <LI>Only with other Monitor contended enter events for the same monitor object:
 *     <UL>
 *     <LI>Monitor Contended Enter Event
 *     </UL>
 * <LI>Only with other Monitor contended entered events for the same monitor object:
 *     <UL>
 *     <LI>Monitor Contended Entered Event
 *    </UL>
 * <LI>Only with other Monitor wait events for the same monitor object:
 *     <UL>
 *     <LI>Monitor Wait Event
 *     </UL>
 * <LI>Only with other Monitor waited events for the same monitor object:
 *     <UL>
 *     <LI>Monitor Waited Event
 *     </UL>
 * <LI>Only with other members of this group, at the same location
 * and in the same thread:
 *     <UL>
 *     <LI>{@link BreakpointEvent}
 *     <LI>{@link StepEvent}
 *     <LI>{@link MethodEntryEvent}
 *     </UL>
 * </UL>
 *
 * @see Event
 * @see EventQueue
 *
 * @author Robert Field
 * @since  1.3
 */

public interface EventSet extends Mirror, Set<Event> {

    /**
     * Returns the policy used to suspend threads in the target VM
     * for this event set. This policy is selected from the suspend
     * policies for each event's request; the target VM chooses the
     * policy which suspends the most threads.  The target VM
     * suspends threads according to that policy
     * and that policy is returned here. See
     * {@link com.sun.jdi.request.EventRequest} for the possible
     * policy values.
     * <p>
     * In rare cases, the suspend policy may differ from the requested
     * value if a {@link ClassPrepareEvent} has occurred in a
     * debugger system thread. See {@link ClassPrepareEvent#thread}
     * for details.
     *
     * @return the suspendPolicy which is either
     * {@link com.sun.jdi.request.EventRequest#SUSPEND_ALL SUSPEND_ALL},
     * {@link com.sun.jdi.request.EventRequest#SUSPEND_EVENT_THREAD SUSPEND_EVENT_THREAD} or
     * {@link com.sun.jdi.request.EventRequest#SUSPEND_NONE SUSPEND_NONE}.
     */
    int suspendPolicy();

    /**
     * Return an iterator specific to {@link Event} objects.
     */
    EventIterator eventIterator();

    /**
     * Resumes threads suspended by this event set. If the {@link #suspendPolicy}
     * is {@link com.sun.jdi.request.EventRequest#SUSPEND_ALL}, a call
     * to this method is equivalent to
     * {@link com.sun.jdi.VirtualMachine#resume}. If the
     * suspend policy is
     * {@link com.sun.jdi.request.EventRequest#SUSPEND_EVENT_THREAD},
     * a call to this method is equivalent to
     * {@link com.sun.jdi.ThreadReference#resume} for the event thread.
     * Otherwise, a call to this method is a no-op.
     */
    void resume();
}
