Intersect.java :  » Library » JavaMutex » com » farsight_systems » concurrent » Java Open Source

Java Open Source » Library » JavaMutex 
JavaMutex » com » farsight_systems » concurrent » Intersect.java
//COPYRIGHT (c) 2007-2010 FARSIGHT SYSTEMS CORPORATION - ALL RIGHTS RESERVED.

package com.farsight_systems.concurrent;

import java.util.concurrent.TimeUnit;

/**
 * The public API for an {@code Intersect} that allows participants
 * to enter via a particular {@link Pathway} waiting until all other
 * {@code Pathway} have released their access. If multiple threads each specify
 * the same {@code Pathway} for this {@code Intersect}, then they will
 * all share access to the {@code Intersect}. A thread is delayed only
 * when it specifies a different {@code Pathway} while the {@code Intersect}
 * is being accessed.
 *<p/>
 * An application that wants to limit the number of concurrent participants
 * for a particular {@code Pathway} can provide a wrapper class that combines the
 * {@code Intersect} and a {@link Semaphore}.
 * See {@link IntersectLimited} for an example class that limits the
 * number of concurrent {@code Pathway} accessors.
 *<p/>
 * Multiple threads may concurrently access a particular {@code Pathway}
 * in essentially a read-only manner. Thus, a {@code Pathway} is a
 * logical group of read-only accessors (threads). Other groups that
 * are represented by other {@code Pathway} instances are synchronized
 * with each other by the owning {@code Intersect}. Thus, the threads
 * that are currently accessing a particular {@code Pathway} are
 * co-operating as a group in a read-only (shared) mode on the logical resource implied
 * by the {@code Intersect}, and each group is co-operating with other groups (i.e.,
 * other distinct {@code Pathway} instances) in a read-write (exclusive) mode.
 *<p/>
 * If multiple threads are accessing a specific {@code Pathway} for updating a logical
 * resource, then that resource requires its own read-write synchronization
 * or locking protocol.
 *<p/>
 *<pre>
 *                                  Intersect
 *                                +-----------+
 *                                | RESOURCE  |
 *                                +-----------+
 *                                      |
 *                                      V
 *            +----------------+--------+--------+----------------+
 *            |                |                 |                |
 *            V                V                 V                V
 *         Pathway          Pathway           Pathway          Pathway
 *       +---------+      +---------+       +---------+      +---------+
 *       |  GROUP  |      |  GROUP  |       |  GROUP  |      |  GROUP  |
 *       +---------+      +---------+       +---------+      +---------+
 *</pre>
 * Each logical group is read-write (exclusive) synchronized with the other
 * groups. Within each group, the threads are read-only (shared) synchronized with
 * each other thread in that group. The group that currently has access to the
 * resource must provide its own synchronization or locking protocol for its
 * multiple threads to update the resource. If there is one thread in the
 * group, then no further synchronization or locking is required.
 *<p/>
 * A {@code Pathway} is <em>owned</em> by a particular {@code Intersect}
 * instance and cannot be used by any other {@code Intersect} instance.
 *<p/>
 * The {@code Pathway} may represent a <em>virtual task</em> acquiring
 * exclusive control of the logical resource that is represented by the
 * {@code Intersect}. A "dispatcher" thread that is managing the
 * <em>virtual task</em> should use the timed access methods with a
 * duration of zero to poll for availability. If the {@code Intersect}
 * is unavailable, the "dispatcher" thread will mark the <em>virtual task</em>
 * as suspended awaiting for the resource, and then dispatch another
 * <em>virtual task</em>. Use the {@link IntersectAvailable}
 * API to notify the "dispatcher" thread to retry the access request.
 *<p/>
 * The {@code IntersectAvailable} API is designed for notifying the application
 * when the {@code Intersect} is fully released. The call back method is invoked
 * by the JVM thread that performed the release. Due to the vagaries of the JVM
 * dispatching algorithm, the {@code Intersect} may be re-acquired by any {@code Pathway}
 * before the call back method is invoked.
 *<p/>
 * The application must guarantee that each successful {@link #access(Pathway)}
 * is paired with {@link #release(Pathway)} for the same {@link Pathway}.
 * <pre>
 *      private final Intersect intersect = new IntersectLatch();
 *      private final Pathway pathway = intersect.createPathway();
 *      private final long duration = 1000000000L; // 1 second
 *
 *      public void doSomething()
 *      throws InterruptedException
 *      {
 *          intersect.access(pathway);
 *          try
 *          {
 *              // the pathway for the intersect is now accessible.
 *          }
 *          finally
 *          {
 *              intersect.release(pathway);
 *          }
 *
 *          if(intersect.access(pathway,duration))
 *          {
 *              try
 *              {
 *                  // the pathway for the intersect is now accessible.
 *              }
 *              finally
 *              {
 *                  intersect.release(pathway);
 *              }
 *          }
 *      }
 * </pre>
 *<p/>
 * The {@code Pathway} has convenience methods that omit the {@code Intersect}
 * reference to use the implied (owning) {@code Intersect}.
 *<pre>
 *      private final Intersect intersect = new IntersectLatch();
 *      private final Pathway pathway = intersect.createPathway();
 *      private final long duration = 1000000000L; // 1 second
 *
 *      public void doSomething()
 *      throws InterruptedException
 *      {
 *          pathway.access();
 *          try
 *          {
 *              // the pathway for the intersect is now accessible.
 *          }
 *          finally
 *          {
 *              pathway.release();
 *          }
 *
 *          if(pathway.access(duration))
 *          {
 *              try
 *              {
 *                  // the pathway for the intersect is now accessible.
 *              }
 *              finally
 *              {
 *                  pathway.release();
 *              }
 *          }
 *      }
 *</pre>
 *<p/>
 * The thread that accesses the {@code Intersect} need not be the same
 * thread that releases the {@code Intersect} for a particular {@code Pathway}.
 *<p/>
 * <strong>Memory accesses</strong> occuring in a thread prior to returning
 * from releasing an {@code Intersect} with a {@code Pathway}
 * <em>happen before</em> memory accesses occuring in another thread subsequent
 * to successfully acquiring that {@code Intersect} with a different {@code Pathway}.
 *
 * @author Jeffrey D. Smith
 * @version 2010-MAY-06c JDS
 * @version 2010-MAY-05 JDS
 * @version 2010-MAY-04 JDS
 * @version 2010-MAY-03 JDS
 * @version 2010-MAY-01 JDS
 * @version 2009-FEB-03 JDS
 */
public interface Intersect
{
    /**
     * Dispense a new instance of {@link Pathway} for this {@link Intersect}.
     * The created {@code Pathway} represents a unique access to the resource
     * represented by the {@code Intersect}. The created {@code Pathway} can
     * only be used by this instance of {@code Intersect}.
     *
     * @return A {@code Pathway} for this {@code Intersect}.
     */
    public abstract Pathway createPathway();

    /**
     * Get the current number of reentrant accesses by the specified {@code Pathway}.
     *<p/>
     * This is the same as calling {@link Pathway#accesses(Intersect) thePathway.accesses(this)}.
     *
     * @param thePathway    The {@code Pathway}.
     *
     * @return The current number of accesses.
     *
     * @throws IllegalArgumentException The {@code Pathway} is owned by another {@code Intersect}.
     */
    public abstract int accesses(Pathway thePathway);

    /**
     * Acquire access to the {@code Intersect}, waiting indefinitely
     * until available. This
     * method will delay subsequent access from other pathways and return
     * to the caller when all other pathways are released.
     *<p/>
     * This is the same as calling {@link Pathway#accessUninterruptibly(Intersect) thePathway.accessUninterruptibly(this)}.
     *
     * @param thePathway    The {@link Pathway} attempting to access the {@code Intersect}.
     *
     * @throws IllegalArgumentException The {@code Pathway} is owned by another {@code Intersect}.
     */
    public abstract void accessUninterruptibly(Pathway thePathway);

    /**
     * Acquire access to the {@code Intersect}, waiting indefinitely
     * until available or throwing {@code InterruptedException}. This
     * method will delay subsequent access from other pathways and return
     * to the caller when all other pathways are released.
     *<p/>
     * This is the same as calling {@link Pathway#access(Intersect) thePathway.access(this)}.
     *<p/>
     * This method is an explicit interrupt point. A pending interrupt
     * will be thrown upon entry or when detected while waiting for the
     * intersect.
     *
     * @param thePathway    The {@link Pathway} attempting to access the {@code Intersect}.
     *
     * @throws IllegalArgumentException The {@code Pathway} is owned by another {@code Intersect}.
     * @throws InterruptedException     The current thread was interrupted before acquiring access.
     */
    public abstract void access(Pathway thePathway)
    throws InterruptedException;

    /**
     * Acquire access to the {@code Intersect}, waiting up to the
     * specified duration until available or throwing {@code InterruptedException}.
     *<p/>
     * This is the same as calling {@link Pathway#access(Intersect,long) thePathway.access(this,theDuration)}.
     *<p/>
     * This method is an explicit interrupt point. A pending interrupt
     * will be thrown upon entry or when detected while waiting for the
     * intersect.
     *
     * @param thePathway    The {@link Pathway} attempting to access the {@code Intersect}.
     * @param theDuration   The maximum duration in nanoseconds. Zero means no waiting.
     *
     * @return {@code true} The {@code Intersect} was acquired before the duration expired.
     *
     * @throws IllegalArgumentException The {@code Pathway} is owned by another {@code Intersect}.
     * @throws InterruptedException     The current thread was interrupted before acquiring access.
     */
    public abstract boolean access(Pathway thePathway, long theDuration)
    throws InterruptedException;

    /**
     * Acquire access to the {@code Intersect}, waiting up to the
     * specified duration until available or throwing {@code InterruptedException}.
     *<p/>
     * This is the same as calling
     * {@link #access(Pathway,long) access(thePathway,theTimeUnit.toNanos(theDuration))}.
     *<p/>
     * This is the same as calling {@link Pathway#access(Intersect,long,TimeUnit) thePathway.access(this,theDuration,theTimeUnit)}.
     *<p/>
     * This method is an explicit interrupt point. A pending interrupt
     * will be thrown upon entry or when detected while waiting for the
     * intersect.
     *
     * @param thePathway    The {@link Pathway} attempting to access the {@code Intersect}.
     * @param theDuration   The maximum duration to wait. Zero means no waiting.
     * @param theTimeUnit   The TimeUnit of measure for the duration.
     *
     * @return {@code true} The {@code Intersect} was acquired before the duration expired.
     *
     * @throws IllegalArgumentException The {@code Pathway} is owned by another {@code Intersect}.
     * @throws InterruptedException     The current thread was interrupted before acquiring access.
     */
    public abstract boolean access(Pathway thePathway, long theDuration, TimeUnit theTimeUnit)
    throws InterruptedException;

    /**
     * Release access to the {@code Intersect} for the specified {@link Pathway}.
     *<p/>
     * This is the same as calling {@link Pathway#release(Intersect) thePathway.release(this)}.
     *
     * @param thePathway    The {@link Pathway} that has access to the {@code Intersect}.
     *
     * @throws IllegalArgumentException     The {@code Pathway} is owned by another {@code Intersect}.
     * @throws IllegalMonitorStateException The {@code Pathway} has no access to the {@code Intersect}.
     */
    public abstract void release(Pathway thePathway);

    /**
     * Get the {@link IntersectAvailable} reference for this instance.
     *
     * @return The {@link IntersectAvailable} reference for this instance.
     */
    public abstract IntersectAvailable getIntersectAvailable();

    /**
     * Set the {@link IntersectAvailable} reference for this instance.
     *
     * @param theIntersectAvailable The next IntersectAvailable reference for this instance.
     *
     * @return The previous {@link IntersectAvailable} reference for this instance.
     */
    public abstract IntersectAvailable setIntersectAvailable(IntersectAvailable theIntersectAvailable);
}
java2s.com  | Contact Us | Privacy Policy
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.