package de.renew.engine.searcher;


/**
 * Interface for a collection of {@link Triggerable} objects
 * that can be triggered by {@link #proposeSearch()}.
 * The primary implementation is {@link TriggerableCollectionImpl}.
 * The Distribute plugin has an own implementation that functions as a proxy
 * for a {@link TriggerableCollectionImpl} in another Java VM via RMI.
 * <p>
 * This interface controls the triggering especially of transitions
 * for the purpose of reinsertion into the search queue.
 * <p>
 * The general picture: *Before* relying on a marking for the analysis
 * of a triggerable's enabledness, the triggerable is registered with
 * the place's triggerable collection.
 * <p>
 * After a change is done to a place, the place's triggerable collection
 * is used to inform all transitions of their possible enabledness.
 * <p>
 * Each transition removes itself from all its triggers.
 * Afterwards it inserts itself into the search queue.
 * <p>
 * This ensures that each marking change is guaranteed to force the
 * reexamination of the affected transitions. Transitions might
 * be examined too often, but only when a change was made
 * during their examination.
 * <p>
 * Lock order for deadlock exclusion:
 * <ol>
 *   <li> triggerable collections
 *   <li> trigger collections
 * </ol>
 * The locking is done by synchronisation.
 * <p>
 * The global data structure:
 * Each triggerable has an associated trigger collection.
 * Triggerable collections reference triggerables and make
 * sure that they are referenced by the associated trigger collections.
 * <p>
 * The associations between trigger collections and triggerable collections
 * cannot be stored in a central data structure, because this would
 * eliminate garbage collection.
 * <p>
 * Because there are now links in both directions, a triggerable
 * references its triggers even after the tokens that gave rise to the
 * possible connection have disappeared. Even if a black token
 * is removed from the input of a triggerable, that triggerable needs
 * to be rechecked, because it might be determined that a
 * triggering is no longer possible. That knowledge would in turn allow
 * garbage collection in some cases.
 */
public interface TriggerableCollection {
    /**
     * Include the given triggerable in this collection.
     * The triggerable is also added to all its triggers.
     * If the triggerable is already in this collection, nothing happens.
     * @param triggerable the triggerable to include
     */
    void include(Triggerable triggerable);

    /**
     * Exclude the given triggerable from this collection.
     * The triggerable is also removed from all its triggers.
     * If the triggerable is not in this collection, nothing happens.
     * @param triggerable the triggerable to exclude
     */
    void exclude(Triggerable triggerable);

    /**
     * Propose a search for all triggerables in this collection.
     * Each triggerable is asked to reinsert itself into the search queue.
     * If a triggerable is not enabled, it will remove itself from
     * all its triggers and not reinsert itself.
     * If a triggerable is enabled, it will reinsert itself into
     * the search queue and remain registered with all its triggers.
     * <p>
     * This method is called when a change was made to a place
     * that might have changed the enabledness of some triggerables.
     * The change might be the addition or removal of tokens,
     * or a time change.
     * <p>
     * This method must be called while holding the lock
     * on this collection. It will synchronise on each triggerable
     * in turn, so the lock order must be observed.
     */
    void proposeSearch();
}