/*
 * Copyright (c) 1998, 2013, Oracle and/or its affiliates. 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.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.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
 */

@jdk.Exported
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();
}
