openjpa-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From p..@apache.org
Subject svn commit: r417856 [21/22] - in /incubator/openjpa/trunk/openjpa-lib: java/ main/ main/java/ main/java/org/apache/openjpa/lib/ant/ main/java/org/apache/openjpa/lib/conf/ main/java/org/apache/openjpa/lib/jdbc/ main/java/org/apache/openjpa/lib/log/ main...
Date Wed, 28 Jun 2006 19:34:40 GMT
Added: incubator/openjpa/trunk/openjpa-lib/main/java/org/apache/openjpa/lib/util/concurrent/Queue.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-lib/main/java/org/apache/openjpa/lib/util/concurrent/Queue.java?rev=417856&view=auto
==============================================================================
--- incubator/openjpa/trunk/openjpa-lib/main/java/org/apache/openjpa/lib/util/concurrent/Queue.java (added)
+++ incubator/openjpa/trunk/openjpa-lib/main/java/org/apache/openjpa/lib/util/concurrent/Queue.java Wed Jun 28 12:34:33 2006
@@ -0,0 +1,207 @@
+/*
+ * Copyright 2006 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/licenses/publicdomain
+ */
+package org.apache.openjpa.lib.util.concurrent;
+
+import java.util.*;
+
+
+/**
+ * A collection designed for holding elements prior to processing.
+ * Besides basic {@link java.util.Collection Collection} operations,
+ * queues provide additional insertion, extraction, and inspection
+ * operations.  Each of these methods exists in two forms: one throws
+ * an exception if the operation fails, the other returns a special
+ * value (either <tt>null</tt> or <tt>false</tt>, depending on the
+ * operation).  The latter form of the insert operation is designed
+ * specifically for use with capacity-restricted <tt>Queue</tt>
+ * implementations; in most implementations, insert operations cannot
+ * fail.
+ *
+ * <p>
+ * <table BORDER CELLPADDING=3 CELLSPACING=1>
+ *  <tr>
+ *    <td></td>
+ *    <td ALIGN=CENTER><em>Throws exception</em></td>
+ *    <td ALIGN=CENTER><em>Returns special value</em></td>
+ *  </tr>
+ *  <tr>
+ *    <td><b>Insert</b></td>
+ *    <td>{@link #add add(e)}</td>
+ *    <td>{@link #offer offer(e)}</td>
+ *  </tr>
+ *  <tr>
+ *    <td><b>Remove</b></td>
+ *    <td>{@link #remove remove()}</td>
+ *    <td>{@link #poll poll()}</td>
+ *  </tr>
+ *  <tr>
+ *    <td><b>Examine</b></td>
+ *    <td>{@link #element element()}</td>
+ *    <td>{@link #peek peek()}</td>
+ *  </tr>
+ * </table>
+ *
+ * <p>Queues typically, but do not necessarily, order elements in a
+ * FIFO (first-in-first-out) manner.  Among the exceptions are
+ * priority queues, which order elements according to a supplied
+ * comparator, or the elements' natural ordering, and LIFO queues (or
+ * stacks) which order the elements LIFO (last-in-first-out).
+ * Whatever the ordering used, the <em>head</em> of the queue is that
+ * element which would be removed by a call to {@link #remove() } or
+ * {@link #poll()}.  In a FIFO queue, all new elements are inserted at
+ * the <em> tail</em> of the queue. Other kinds of queues may use
+ * different placement rules.  Every <tt>Queue</tt> implementation
+ * must specify its ordering properties.
+ *
+ * <p>The {@link #offer offer} method inserts an element if possible,
+ * otherwise returning <tt>false</tt>.  This differs from the {@link
+ * java.util.Collection#add Collection.add} method, which can fail to
+ * add an element only by throwing an unchecked exception.  The
+ * <tt>offer</tt> method is designed for use when failure is a normal,
+ * rather than exceptional occurrence, for example, in fixed-capacity
+ * (or &quot;bounded&quot;) queues.
+ *
+ * <p>The {@link #remove()} and {@link #poll()} methods remove and
+ * return the head of the queue.
+ * Exactly which element is removed from the queue is a
+ * function of the queue's ordering policy, which differs from
+ * implementation to implementation. The <tt>remove()</tt> and
+ * <tt>poll()</tt> methods differ only in their behavior when the
+ * queue is empty: the <tt>remove()</tt> method throws an exception,
+ * while the <tt>poll()</tt> method returns <tt>null</tt>.
+ *
+ * <p>The {@link #element()} and {@link #peek()} methods return, but do
+ * not remove, the head of the queue.
+ *
+ * <p>The <tt>Queue</tt> interface does not define the <i>blocking queue
+ * methods</i>, which are common in concurrent programming.  These methods,
+ * which wait for elements to appear or for space to become available, are
+ * defined in the {@link edu.emory.mathcs.backport.java.util.concurrent.BlockingQueue} interface, which
+ * extends this interface.
+ *
+ * <p><tt>Queue</tt> implementations generally do not allow insertion
+ * of <tt>null</tt> elements, although some implementations, such as
+ * {@link LinkedList}, do not prohibit insertion of <tt>null</tt>.
+ * Even in the implementations that permit it, <tt>null</tt> should
+ * not be inserted into a <tt>Queue</tt>, as <tt>null</tt> is also
+ * used as a special return value by the <tt>poll</tt> method to
+ * indicate that the queue contains no elements.
+ *
+ * <p><tt>Queue</tt> implementations generally do not define
+ * element-based versions of methods <tt>equals</tt> and
+ * <tt>hashCode</tt> but instead inherit the identity based versions
+ * from class <tt>Object</tt>, because element-based equality is not
+ * always well-defined for queues with the same elements but different
+ * ordering properties.
+ *
+ *
+ * <p>This interface is a member of the
+ * <a href="{@docRoot}/../guide/collections/index.html">
+ * Java Collections Framework</a>.
+ *
+ * @see java.util.Collection
+ * @see LinkedList
+ * @see PriorityQueue
+ * @see edu.emory.mathcs.backport.java.util.concurrent.LinkedBlockingQueue
+ * @see edu.emory.mathcs.backport.java.util.concurrent.BlockingQueue
+ * @see edu.emory.mathcs.backport.java.util.concurrent.ArrayBlockingQueue
+ * @see edu.emory.mathcs.backport.java.util.concurrent.LinkedBlockingQueue
+ * @see edu.emory.mathcs.backport.java.util.concurrent.PriorityBlockingQueue
+ * @since 1.5
+ * @author Doug Lea
+ */
+public interface Queue extends Collection {
+    /**
+     * Inserts the specified element into this queue if it is possible to do so
+     * immediately without violating capacity restrictions, returning
+     * <tt>true</tt> upon success and throwing an <tt>IllegalStateException</tt>
+     * if no space is currently available.
+     *
+     * @param e the element to add
+     * @return <tt>true</tt> (as specified by {@link Collection#add})
+     * @throws IllegalStateException if the element cannot be added at this
+     *         time due to capacity restrictions
+     * @throws ClassCastException if the class of the specified element
+     *         prevents it from being added to this queue
+     * @throws NullPointerException if the specified element is null and
+     *         this queue not permit null elements
+     * @throws IllegalArgumentException if some property of this element
+     *         prevents it from being added to this queue
+     */
+    boolean add(Object e);
+
+    /**
+     * Inserts the specified element into this queue if it is possible to do
+     * so immediately without violating capacity restrictions.
+     * When using a capacity-restricted queue, this method is generally
+     * preferable to {@link #add}, which can fail to insert an element only
+     * by throwing an exception.
+     *
+     * @param e the element to add
+     * @return <tt>true</tt> if the element was added to this queue, else
+     *         <tt>false</tt>
+     * @throws ClassCastException if the class of the specified element
+     *         prevents it from being added to this queue
+     * @throws NullPointerException if the specified element is null and
+     *         this queue does not permit null elements
+     * @throws IllegalArgumentException if some property of this element
+     *         prevents it from being added to this queue
+     */
+    boolean offer(Object e);
+
+    /**
+     * Retrieves and removes the head of this queue.  This method differs
+     * from {@link #poll poll} only in that it throws an exception if this
+     * queue is empty.
+     * is empty.
+     *
+     * @return the head of this queue
+     * @throws NoSuchElementException if this queue is empty
+     */
+    Object remove();
+
+    /**
+     * Retrieves and removes the head of this queue,
+     * or returns <tt>null</tt> if this queue is empty.
+     *
+     * @return the head of this queue, or <tt>null</tt> if this queue is empty
+     */
+    Object poll();
+
+    /**
+     * Retrieves, but does not remove, the head of this queue.  This method
+     * differs from {@link #peek peek} only in that it throws an exception
+     * if this queue is empty.
+     *
+     * @return the head of this queue
+     * @throws NoSuchElementException if this queue is empty
+     */
+    Object element();
+
+    /**
+     * Retrieves, but does not remove, the head of this queue,
+     * or returns <tt>null</tt> if this queue is empty.
+     *
+     * @return the head of this queue, or <tt>null</tt> if this queue is empty
+     */
+    Object peek();
+}

Propchange: incubator/openjpa/trunk/openjpa-lib/main/java/org/apache/openjpa/lib/util/concurrent/Queue.java
------------------------------------------------------------------------------
    svn:executable = *

Added: incubator/openjpa/trunk/openjpa-lib/main/java/org/apache/openjpa/lib/util/concurrent/ReentrantLock.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-lib/main/java/org/apache/openjpa/lib/util/concurrent/ReentrantLock.java?rev=417856&view=auto
==============================================================================
--- incubator/openjpa/trunk/openjpa-lib/main/java/org/apache/openjpa/lib/util/concurrent/ReentrantLock.java (added)
+++ incubator/openjpa/trunk/openjpa-lib/main/java/org/apache/openjpa/lib/util/concurrent/ReentrantLock.java Wed Jun 28 12:34:33 2006
@@ -0,0 +1,1025 @@
+/*
+ * Copyright 2006 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/licenses/publicdomain
+ */
+package org.apache.openjpa.lib.util.concurrent;
+
+import java.util.*;
+
+
+/**
+ * A reentrant mutual exclusion {@link Lock} with the same basic
+ * behavior and semantics as the implicit monitor lock accessed using
+ * <tt>synchronized</tt> methods and statements, but with extended
+ * capabilities.
+ *
+ * <p> A <tt>ReentrantLock</tt> is <em>owned</em> by the thread last
+ * successfully locking, but not yet unlocking it. A thread invoking
+ * <tt>lock</tt> will return, successfully acquiring the lock, when
+ * the lock is not owned by another thread. The method will return
+ * immediately if the current thread already owns the lock. This can
+ * be checked using methods {@link #isHeldByCurrentThread}, and {@link
+ * #getHoldCount}.
+ *
+ * <p> The constructor for this class accepts an optional
+ * <em>fairness</em> parameter.  When set <tt>true</tt>, under
+ * contention, locks favor granting access to the longest-waiting
+ * thread.  Otherwise this lock does not guarantee any particular
+ * access order.  Programs using fair locks accessed by many threads
+ * may display lower overall throughput (i.e., are slower; often much
+ * slower) than those using the default setting, but have smaller
+ * variances in times to obtain locks and guarantee lack of
+ * starvation. Note however, that fairness of locks does not guarantee
+ * fairness of thread scheduling. Thus, one of many threads using a
+ * fair lock may obtain it multiple times in succession while other
+ * active threads are not progressing and not currently holding the
+ * lock.
+ * Also note that the untimed {@link #tryLock() tryLock} method does not
+ * honor the fairness setting. It will succeed if the lock
+ * is available even if other threads are waiting.
+ *
+ * <p> It is recommended practice to <em>always</em> immediately
+ * follow a call to <tt>lock</tt> with a <tt>try</tt> block, most
+ * typically in a before/after construction such as:
+ *
+ * <pre>
+ * class X {
+ *   private final ReentrantLock lock = new ReentrantLock();
+ *   // ...
+ *
+ *   public void m() {
+ *     lock.lock();  // block until condition holds
+ *     try {
+ *       // ... method body
+ *     } finally {
+ *       lock.unlock()
+ *     }
+ *   }
+ * }
+ * </pre>
+ *
+ * <p>In addition to implementing the {@link Lock} interface, this
+ * class defines methods <tt>isLocked</tt> and
+ * <tt>getLockQueueLength</tt>, as well as some associated
+ * <tt>protected</tt> access methods that may be useful for
+ * instrumentation and monitoring.
+ *
+ * <p> Serialization of this class behaves in the same way as built-in
+ * locks: a deserialized lock is in the unlocked state, regardless of
+ * its state when serialized.
+ *
+ * <p> This lock supports a maximum of 2147483647 recursive locks by
+ * the same thread. Attempts to exceed this limit result in
+ * {@link Error} throws from locking methods.
+ *
+ * @since 1.5
+ * @author Doug Lea
+ * @author Dawid Kurzyniec
+ */
+public class ReentrantLock implements Lock, java.io.Serializable,
+    CondVar.ExclusiveLock {
+    private static final long serialVersionUID = 7373984872572414699L;
+    private final Sync sync;
+
+    /**
+     * Creates an instance of <tt>ReentrantLock</tt>.
+     * This is equivalent to using <tt>ReentrantLock(false)</tt>.
+     */
+    public ReentrantLock() {
+        sync = new NonfairSync();
+    }
+
+    /**
+     * Creates an instance of <tt>ReentrantLock</tt> with the
+     * given fairness policy.
+     * @param fair true if this lock will be fair; else false
+     */
+    public ReentrantLock(boolean fair) {
+        sync = (fair) ? (Sync) new FairSync() : new NonfairSync();
+    }
+
+    /**
+     * Acquires the lock.
+     *
+     * <p>Acquires the lock if it is not held by another thread and returns
+     * immediately, setting the lock hold count to one.
+     *
+     * <p>If the current thread
+     * already holds the lock then the hold count is incremented by one and
+     * the method returns immediately.
+     *
+     * <p>If the lock is held by another thread then the
+     * current thread becomes disabled for thread scheduling
+     * purposes and lies dormant until the lock has been acquired,
+     * at which time the lock hold count is set to one.
+     */
+    public void lock() {
+        sync.lock();
+    }
+
+    /**
+     * Acquires the lock unless the current thread is
+     * {@link Thread#interrupt interrupted}.
+     *
+     * <p>Acquires the lock if it is not held by another thread and returns
+     * immediately, setting the lock hold count to one.
+     *
+     * <p>If the current thread already holds this lock then the hold count
+     * is incremented by one and the method returns immediately.
+     *
+     * <p>If the lock is held by another thread then the
+     * current thread becomes disabled for thread scheduling
+     * purposes and lies dormant until one of two things happens:
+     *
+     * <ul>
+     *
+     * <li>The lock is acquired by the current thread; or
+     *
+     * <li>Some other thread {@link Thread#interrupt interrupts} the current
+     * thread.
+     *
+     * </ul>
+     *
+     * <p>If the lock is acquired by the current thread then the lock hold
+     * count is set to one.
+     *
+     * <p>If the current thread:
+     *
+     * <ul>
+     *
+     * <li>has its interrupted status set on entry to this method; or
+     *
+     * <li>is {@link Thread#interrupt interrupted} while acquiring
+     * the lock,
+     *
+     * </ul>
+     *
+     * then {@link InterruptedException} is thrown and the current thread's
+     * interrupted status is cleared.
+     *
+     * <p>In this implementation, as this method is an explicit interruption
+     * point, preference is
+     * given to responding to the interrupt over normal or reentrant
+     * acquisition of the lock.
+     *
+     * @throws InterruptedException if the current thread is interrupted
+     */
+    public void lockInterruptibly() throws InterruptedException {
+        sync.lockInterruptibly();
+    }
+
+    /**
+     * Acquires the lock only if it is not held by another thread at the time
+     * of invocation.
+     *
+     * <p>Acquires the lock if it is not held by another thread and
+     * returns immediately with the value <tt>true</tt>, setting the
+     * lock hold count to one. Even when this lock has been set to use a
+     * fair ordering policy, a call to <tt>tryLock()</tt> <em>will</em>
+     * immediately acquire the lock if it is available, whether or not
+     * other threads are currently waiting for the lock.
+     * This &quot;barging&quot; behavior can be useful in certain
+     * circumstances, even though it breaks fairness. If you want to honor
+     * the fairness setting for this lock, then use
+     * {@link #tryLock(long, TimeUnit) tryLock(0, TimeUnit.SECONDS) }
+     * which is almost equivalent (it also detects interruption).
+     *
+     * <p> If the current thread
+     * already holds this lock then the hold count is incremented by one and
+     * the method returns <tt>true</tt>.
+     *
+     * <p>If the lock is held by another thread then this method will return
+     * immediately with the value <tt>false</tt>.
+     *
+     * @return <tt>true</tt> if the lock was free and was acquired by the
+     * current thread, or the lock was already held by the current thread; and
+     * <tt>false</tt> otherwise.
+     */
+    public boolean tryLock() {
+        return sync.tryLock();
+    }
+
+    /**
+     * Acquires the lock if it is not held by another thread within the given
+     * waiting time and the current thread has not been
+     * {@link Thread#interrupt interrupted}.
+     *
+     * <p>Acquires the lock if it is not held by another thread and returns
+     * immediately with the value <tt>true</tt>, setting the lock hold count
+     * to one. If this lock has been set to use a fair ordering policy then
+     * an available lock <em>will not</em> be acquired if any other threads
+     * are waiting for the lock. This is in contrast to the {@link #tryLock()}
+     * method. If you want a timed <tt>tryLock</tt> that does permit barging on
+     * a fair lock then combine the timed and un-timed forms together:
+     *
+     * <pre>if (lock.tryLock() || lock.tryLock(timeout, unit) ) { ... }
+     * </pre>
+     *
+     * <p>If the current thread
+     * already holds this lock then the hold count is incremented by one and
+     * the method returns <tt>true</tt>.
+     *
+     * <p>If the lock is held by another thread then the
+     * current thread becomes disabled for thread scheduling
+     * purposes and lies dormant until one of three things happens:
+     *
+     * <ul>
+     *
+     * <li>The lock is acquired by the current thread; or
+     *
+     * <li>Some other thread {@link Thread#interrupt interrupts} the current
+     * thread; or
+     *
+     * <li>The specified waiting time elapses
+     *
+     * </ul>
+     *
+     * <p>If the lock is acquired then the value <tt>true</tt> is returned and
+     * the lock hold count is set to one.
+     *
+     * <p>If the current thread:
+     *
+     * <ul>
+     *
+     * <li>has its interrupted status set on entry to this method; or
+     *
+     * <li>is {@link Thread#interrupt interrupted} while acquiring
+     * the lock,
+     *
+     * </ul>
+     * then {@link InterruptedException} is thrown and the current thread's
+     * interrupted status is cleared.
+     *
+     * <p>If the specified waiting time elapses then the value <tt>false</tt>
+     * is returned.
+     * If the time is
+     * less than or equal to zero, the method will not wait at all.
+     *
+     * <p>In this implementation, as this method is an explicit interruption
+     * point, preference is
+     * given to responding to the interrupt over normal or reentrant
+     * acquisition of the lock, and over reporting the elapse of the waiting
+     * time.
+     *
+     * @param timeout the time to wait for the lock
+     * @param unit the time unit of the timeout argument
+     *
+     * @return <tt>true</tt> if the lock was free and was acquired by the
+     * current thread, or the lock was already held by the current thread; and
+     * <tt>false</tt> if the waiting time elapsed before the lock could be
+     * acquired.
+     *
+     * @throws InterruptedException if the current thread is interrupted
+     * @throws NullPointerException if unit is null
+     *
+     */
+    public boolean tryLock(long timeout, TimeUnit unit)
+        throws InterruptedException {
+        return sync.tryLock(unit.toNanos(timeout));
+    }
+
+    /**
+     * Attempts to release this lock.
+     *
+     * <p>If the current thread is the
+     * holder of this lock then the hold count is decremented. If the
+     * hold count is now zero then the lock is released.  If the
+     * current thread is not the holder of this lock then {@link
+     * IllegalMonitorStateException} is thrown.
+     * @throws IllegalMonitorStateException if the current thread does not
+     * hold this lock.
+     */
+    public void unlock() {
+        sync.unlock();
+    }
+
+    /**
+     * Returns a {@link Condition} instance for use with this
+     * {@link Lock} instance.
+     *
+     * <p>The returned {@link Condition} instance supports the same
+     * usages as do the {@link Object} monitor methods ({@link
+     * Object#wait() wait}, {@link Object#notify notify}, and {@link
+     * Object#notifyAll notifyAll}) when used with the built-in
+     * monitor lock.
+     *
+     * <ul>
+     *
+     * <li>If this lock is not held when any of the {@link Condition}
+     * {@link Condition#await() waiting} or {@link Condition#signal
+     * signalling} methods are called, then an {@link
+     * IllegalMonitorStateException} is thrown.
+     *
+     * <li>When the condition {@link Condition#await() waiting}
+     * methods are called the lock is released and, before they
+     * return, the lock is reacquired and the lock hold count restored
+     * to what it was when the method was called.
+     *
+     * <li>If a thread is {@link Thread#interrupt interrupted} while
+     * waiting then the wait will terminate, an {@link
+     * InterruptedException} will be thrown, and the thread's
+     * interrupted status will be cleared.
+     *
+     * <li> Waiting threads are signalled in FIFO order
+     *
+     * <li>The ordering of lock reacquisition for threads returning
+     * from waiting methods is the same as for threads initially
+     * acquiring the lock, which is in the default case not specified,
+     * but for <em>fair</em> locks favors those threads that have been
+     * waiting the longest.
+     *
+     * </ul>
+     *
+     * @return the Condition object
+     */
+    public Condition newCondition() {
+        return isFair() ? new FIFOCondVar(this) : new CondVar(this);
+    }
+
+    /**
+     * Queries the number of holds on this lock by the current thread.
+     *
+     * <p>A thread has a hold on a lock for each lock action that is not
+     * matched by an unlock action.
+     *
+     * <p>The hold count information is typically only used for testing and
+     * debugging purposes. For example, if a certain section of code should
+     * not be entered with the lock already held then we can assert that
+     * fact:
+     *
+     * <pre>
+     * class X {
+     *   ReentrantLock lock = new ReentrantLock();
+     *   // ...
+     *   public void m() {
+     *     assert lock.getHoldCount() == 0;
+     *     lock.lock();
+     *     try {
+     *       // ... method body
+     *     } finally {
+     *       lock.unlock();
+     *     }
+     *   }
+     * }
+     * </pre>
+     *
+     * @return the number of holds on this lock by the current thread,
+     * or zero if this lock is not held by the current thread.
+     */
+    public int getHoldCount() {
+        return sync.getHoldCount();
+    }
+
+    /**
+     * Queries if this lock is held by the current thread.
+     *
+     * <p>Analogous to the {@link Thread#holdsLock} method for built-in
+     * monitor locks, this method is typically used for debugging and
+     * testing. For example, a method that should only be called while
+     * a lock is held can assert that this is the case:
+     *
+     * <pre>
+     * class X {
+     *   ReentrantLock lock = new ReentrantLock();
+     *   // ...
+     *
+     *   public void m() {
+     *       assert lock.isHeldByCurrentThread();
+     *       // ... method body
+     *   }
+     * }
+     * </pre>
+     *
+     * <p>It can also be used to ensure that a reentrant lock is used
+     * in a non-reentrant manner, for example:
+     *
+     * <pre>
+     * class X {
+     *   ReentrantLock lock = new ReentrantLock();
+     *   // ...
+     *
+     *   public void m() {
+     *       assert !lock.isHeldByCurrentThread();
+     *       lock.lock();
+     *       try {
+     *           // ... method body
+     *       } finally {
+     *           lock.unlock();
+     *       }
+     *   }
+     * }
+     * </pre>
+     * @return <tt>true</tt> if current thread holds this lock and
+     * <tt>false</tt> otherwise.
+     */
+    public boolean isHeldByCurrentThread() {
+        return sync.isHeldByCurrentThread();
+    }
+
+    /**
+     * Queries if this lock is held by any thread. This method is
+     * designed for use in monitoring of the system state,
+     * not for synchronization control.
+     * @return <tt>true</tt> if any thread holds this lock and
+     * <tt>false</tt> otherwise.
+     */
+    public boolean isLocked() {
+        return sync.isLocked();
+    }
+
+    /**
+     * Returns true if this lock has fairness set true.
+     * @return true if this lock has fairness set true.
+     */
+    public final boolean isFair() {
+        return sync.isFair();
+    }
+
+    /**
+     * <tt>null</tt> if not owned. When this method is called by a
+     * thread that is not the owner, the return value reflects a
+     * best-effort approximation of current lock status. For example,
+     * the owner may be momentarily <tt>null</tt> even if there are
+     * threads trying to acquire the lock but have not yet done so.
+     * This method is designed to facilitate construction of
+     * subclasses that provide more extensive lock monitoring
+     * facilities.
+     *
+     * @return the owner, or <tt>null</tt> if not owned
+     */
+    protected Thread getOwner() {
+        return sync.getOwner();
+    }
+
+    /**
+     * Queries whether any threads are waiting to acquire this lock. Note that
+     * because cancellations may occur at any time, a <tt>true</tt>
+     * return does not guarantee that any other thread will ever
+     * acquire this lock.  This method is designed primarily for use in
+     * monitoring of the system state.
+     *
+     * @return true if there may be other threads waiting to acquire
+     * the lock.
+     */
+    public final boolean hasQueuedThreads() {
+        return sync.hasQueuedThreads();
+    }
+
+    /**
+     * Queries whether the given thread is waiting to acquire this
+     * lock. Note that because cancellations may occur at any time, a
+     * <tt>true</tt> return does not guarantee that this thread
+     * will ever acquire this lock.  This method is designed primarily for use
+     * in monitoring of the system state.
+     *
+     * @param thread the thread
+     * @return true if the given thread is queued waiting for this lock.
+     * @throws NullPointerException if thread is null
+     */
+    public final boolean hasQueuedThread(Thread thread) {
+        return sync.isQueued(thread);
+    }
+
+    /**
+     * Returns an estimate of the number of threads waiting to
+     * acquire this lock.  The value is only an estimate because the number of
+     * threads may change dynamically while this method traverses
+     * internal data structures.  This method is designed for use in
+     * monitoring of the system state, not for synchronization
+     * control.
+     * @return the estimated number of threads waiting for this lock
+     */
+    public final int getQueueLength() {
+        return sync.getQueueLength();
+    }
+
+    /**
+     * Returns a collection containing threads that may be waiting to
+     * acquire this lock.  Because the actual set of threads may change
+     * dynamically while constructing this result, the returned
+     * collection is only a best-effort estimate.  The elements of the
+     * returned collection are in no particular order.  This method is
+     * designed to facilitate construction of subclasses that provide
+     * more extensive monitoring facilities.
+     * @return the collection of threads
+     */
+    protected Collection getQueuedThreads() {
+        return sync.getQueuedThreads();
+    }
+
+    /**
+     * Queries whether any threads are waiting on the given condition
+     * associated with this lock. Note that because timeouts and
+     * interrupts may occur at any time, a <tt>true</tt> return does
+     * not guarantee that a future <tt>signal</tt> will awaken any
+     * threads.  This method is designed primarily for use in
+     * monitoring of the system state.
+     * @param condition the condition
+     * @return <tt>true</tt> if there are any waiting threads.
+     * @throws IllegalMonitorStateException if this lock
+     * is not held
+     * @throws IllegalArgumentException if the given condition is
+     * not associated with this lock
+     * @throws NullPointerException if condition null
+     */
+    public boolean hasWaiters(Condition condition) {
+        return asCondVar(condition).hasWaiters();
+    }
+
+    /**
+     * Returns an estimate of the number of threads waiting on the
+     * given condition associated with this lock. Note that because
+     * timeouts and interrupts may occur at any time, the estimate
+     * serves only as an upper bound on the actual number of waiters.
+     * This method is designed for use in monitoring of the system
+     * state, not for synchronization control.
+     * @param condition the condition
+     * @return the estimated number of waiting threads.
+     * @throws IllegalMonitorStateException if this lock
+     * is not held
+     * @throws IllegalArgumentException if the given condition is
+     * not associated with this lock
+     * @throws NullPointerException if condition null
+     */
+    public int getWaitQueueLength(Condition condition) {
+        return asCondVar(condition).getWaitQueueLength();
+    }
+
+    /**
+     * Returns a collection containing those threads that may be
+     * waiting on the given condition associated with this lock.
+     * Because the actual set of threads may change dynamically while
+     * constructing this result, the returned collection is only a
+     * best-effort estimate. The elements of the returned collection
+     * are in no particular order.  This method is designed to
+     * facilitate construction of subclasses that provide more
+     * extensive condition monitoring facilities.
+     * @param condition the condition
+     * @return the collection of threads
+     * @throws IllegalMonitorStateException if this lock
+     * is not held
+     * @throws IllegalArgumentException if the given condition is
+     * not associated with this lock
+     * @throws NullPointerException if condition null
+     */
+    protected Collection getWaitingThreads(Condition condition) {
+        return asCondVar(condition).getWaitingThreads();
+    }
+
+    /**
+     * Returns a string identifying this lock, as well as its lock
+     * state.  The state, in brackets, includes either the String
+     * &quot;Unlocked&quot; or the String &quot;Locked by&quot;
+     * followed by the {@link Thread#getName} of the owning thread.
+     * @return a string identifying this lock, as well as its lock state.
+     */
+    public String toString() {
+        Thread o = getOwner();
+
+        return super.toString() +
+        ((o == null) ? "[Unlocked]" : ("[Locked by thread " + o.getName() +
+        "]"));
+    }
+
+    private CondVar asCondVar(Condition condition) {
+        if (condition == null) {
+            throw new NullPointerException();
+        }
+
+        if (!(condition instanceof CondVar)) {
+            throw new IllegalArgumentException("not owner");
+        }
+
+        CondVar condVar = (CondVar) condition;
+
+        if (condVar.lock != this) {
+            throw new IllegalArgumentException("not owner");
+        }
+
+        return condVar;
+    }
+
+    static abstract class Sync implements java.io.Serializable {
+        private static final long serialVersionUID = -5179523762034025860L;
+        protected transient Thread owner_ = null;
+        protected transient int holds_ = 0;
+
+        protected Sync() {
+        }
+
+        public abstract void lock();
+
+        public abstract void lockInterruptibly() throws InterruptedException;
+
+        final void incHolds() {
+            int nextHolds = ++holds_;
+
+            if (nextHolds < 0) {
+                throw new Error("Maximum lock count exceeded");
+            }
+
+            holds_ = nextHolds;
+        }
+
+        public boolean tryLock() {
+            Thread caller = Thread.currentThread();
+
+            synchronized (this) {
+                if (owner_ == null) {
+                    owner_ = caller;
+                    holds_ = 1;
+
+                    return true;
+                } else if (caller == owner_) {
+                    incHolds();
+
+                    return true;
+                }
+            }
+
+            return false;
+        }
+
+        public abstract boolean tryLock(long nanos) throws InterruptedException;
+
+        public abstract void unlock();
+
+        public synchronized int getHoldCount() {
+            return isHeldByCurrentThread() ? holds_ : 0;
+        }
+
+        public synchronized boolean isHeldByCurrentThread() {
+            return (holds_ > 0) && (Thread.currentThread() == owner_);
+        }
+
+        public synchronized boolean isLocked() {
+            return owner_ != null;
+        }
+
+        public abstract boolean isFair();
+
+        protected synchronized Thread getOwner() {
+            return owner_;
+        }
+
+        public boolean hasQueuedThreads() {
+            throw new UnsupportedOperationException("Use FAIR version");
+        }
+
+        public int getQueueLength() {
+            throw new UnsupportedOperationException("Use FAIR version");
+        }
+
+        public Collection getQueuedThreads() {
+            throw new UnsupportedOperationException("Use FAIR version");
+        }
+
+        public boolean isQueued(Thread thread) {
+            throw new UnsupportedOperationException("Use FAIR version");
+        }
+    }
+
+    final static class NonfairSync extends Sync {
+        private static final long serialVersionUID = 7316153563782823691L;
+
+        NonfairSync() {
+        }
+
+        public void lock() {
+            Thread caller = Thread.currentThread();
+
+            synchronized (this) {
+                if (owner_ == null) {
+                    owner_ = caller;
+                    holds_ = 1;
+
+                    return;
+                } else if (caller == owner_) {
+                    incHolds();
+
+                    return;
+                } else {
+                    boolean wasInterrupted = Thread.interrupted();
+
+                    try {
+                        while (true) {
+                            try {
+                                wait();
+                            } catch (InterruptedException e) {
+                                wasInterrupted = true;
+
+                                // no need to notify; if we were signalled, we
+                                // will act as signalled, ignoring the
+                                // interruption
+                            }
+
+                            if (owner_ == null) {
+                                owner_ = caller;
+                                holds_ = 1;
+
+                                return;
+                            }
+                        }
+                    } finally {
+                        if (wasInterrupted) {
+                            Thread.currentThread().interrupt();
+                        }
+                    }
+                }
+            }
+        }
+
+        public void lockInterruptibly() throws InterruptedException {
+            if (Thread.interrupted()) {
+                throw new InterruptedException();
+            }
+
+            Thread caller = Thread.currentThread();
+
+            synchronized (this) {
+                if (owner_ == null) {
+                    owner_ = caller;
+                    holds_ = 1;
+
+                    return;
+                } else if (caller == owner_) {
+                    incHolds();
+
+                    return;
+                } else {
+                    try {
+                        do {
+                            wait();
+                        } while (owner_ != null);
+
+                        owner_ = caller;
+                        holds_ = 1;
+
+                        return;
+                    } catch (InterruptedException ex) {
+                        if (owner_ == null) {
+                            notify();
+                        }
+
+                        throw ex;
+                    }
+                }
+            }
+        }
+
+        public boolean tryLock(long nanos) throws InterruptedException {
+            if (Thread.interrupted()) {
+                throw new InterruptedException();
+            }
+
+            Thread caller = Thread.currentThread();
+
+            synchronized (this) {
+                if (owner_ == null) {
+                    owner_ = caller;
+                    holds_ = 1;
+
+                    return true;
+                } else if (caller == owner_) {
+                    incHolds();
+
+                    return true;
+                } else if (nanos <= 0) {
+                    return false;
+                } else {
+                    long deadline = Utils.nanoTime() + nanos;
+
+                    try {
+                        for (;;) {
+                            TimeUnit.NANOSECONDS.timedWait(this, nanos);
+
+                            if (caller == owner_) {
+                                incHolds();
+
+                                return true;
+                            } else if (owner_ == null) {
+                                owner_ = caller;
+                                holds_ = 1;
+
+                                return true;
+                            } else {
+                                nanos = deadline - Utils.nanoTime();
+
+                                if (nanos <= 0) {
+                                    return false;
+                                }
+                            }
+                        }
+                    } catch (InterruptedException ex) {
+                        if (owner_ == null) {
+                            notify();
+                        }
+
+                        throw ex;
+                    }
+                }
+            }
+        }
+
+        public synchronized void unlock() {
+            if (Thread.currentThread() != owner_) {
+                throw new IllegalMonitorStateException("Not owner");
+            }
+
+            if (--holds_ == 0) {
+                owner_ = null;
+                notify();
+            }
+        }
+
+        public final boolean isFair() {
+            return false;
+        }
+    }
+
+    final static class FairSync extends Sync implements WaitQueue.QueuedSync {
+        private static final long serialVersionUID = -3000897897090466540L;
+        private transient WaitQueue wq_ = new FIFOWaitQueue();
+
+        FairSync() {
+        }
+
+        public synchronized boolean recheck(WaitQueue.WaitNode node) {
+            Thread caller = Thread.currentThread();
+
+            if (owner_ == null) {
+                owner_ = caller;
+                holds_ = 1;
+
+                return true;
+            } else if (caller == owner_) {
+                incHolds();
+
+                return true;
+            }
+
+            wq_.insert(node);
+
+            return false;
+        }
+
+        public synchronized void takeOver(WaitQueue.WaitNode node) {
+            // assert (holds_ == 1 && owner_ == Thread.currentThread()
+            owner_ = node.getOwner();
+        }
+
+        public void lock() {
+            Thread caller = Thread.currentThread();
+
+            synchronized (this) {
+                if (owner_ == null) {
+                    owner_ = caller;
+                    holds_ = 1;
+
+                    return;
+                } else if (caller == owner_) {
+                    incHolds();
+
+                    return;
+                }
+            }
+
+            WaitQueue.WaitNode n = new WaitQueue.WaitNode();
+            n.doWaitUninterruptibly(this);
+        }
+
+        public void lockInterruptibly() throws InterruptedException {
+            if (Thread.interrupted()) {
+                throw new InterruptedException();
+            }
+
+            Thread caller = Thread.currentThread();
+
+            synchronized (this) {
+                if (owner_ == null) {
+                    owner_ = caller;
+                    holds_ = 1;
+
+                    return;
+                } else if (caller == owner_) {
+                    incHolds();
+
+                    return;
+                }
+            }
+
+            WaitQueue.WaitNode n = new WaitQueue.WaitNode();
+            n.doWait(this);
+        }
+
+        public boolean tryLock(long nanos) throws InterruptedException {
+            if (Thread.interrupted()) {
+                throw new InterruptedException();
+            }
+
+            Thread caller = Thread.currentThread();
+
+            synchronized (this) {
+                if (owner_ == null) {
+                    owner_ = caller;
+                    holds_ = 1;
+
+                    return true;
+                } else if (caller == owner_) {
+                    incHolds();
+
+                    return true;
+                }
+            }
+
+            WaitQueue.WaitNode n = new WaitQueue.WaitNode();
+
+            return n.doTimedWait(this, nanos);
+        }
+
+        protected synchronized WaitQueue.WaitNode getSignallee(Thread caller) {
+            if (caller != owner_) {
+                throw new IllegalMonitorStateException("Not owner");
+            }
+
+            // assert (holds_ > 0)
+            if (holds_ >= 2) { // current thread will keep the lock
+                --holds_;
+
+                return null;
+            }
+
+            // assert (holds_ == 1)
+            WaitQueue.WaitNode w = wq_.extract();
+
+            if (w == null) { // if none, clear for new arrivals
+                owner_ = null;
+                holds_ = 0;
+            }
+
+            return w;
+        }
+
+        public void unlock() {
+            Thread caller = Thread.currentThread();
+
+            for (;;) {
+                WaitQueue.WaitNode w = getSignallee(caller);
+
+                if (w == null) {
+                    return; // no one to signal
+                }
+
+                if (w.signal(this)) {
+                    return; // notify if still waiting, or skip
+                }
+            }
+        }
+
+        public final boolean isFair() {
+            return true;
+        }
+
+        public synchronized boolean hasQueuedThreads() {
+            return wq_.hasNodes();
+        }
+
+        public synchronized int getQueueLength() {
+            return wq_.getLength();
+        }
+
+        public synchronized Collection getQueuedThreads() {
+            return wq_.getWaitingThreads();
+        }
+
+        public synchronized boolean isQueued(Thread thread) {
+            return wq_.isWaiting(thread);
+        }
+
+        private void readObject(java.io.ObjectInputStream in)
+            throws java.io.IOException, ClassNotFoundException {
+            in.defaultReadObject();
+
+            synchronized (this) {
+                wq_ = new FIFOWaitQueue();
+            }
+        }
+    }
+}

Propchange: incubator/openjpa/trunk/openjpa-lib/main/java/org/apache/openjpa/lib/util/concurrent/ReentrantLock.java
------------------------------------------------------------------------------
    svn:executable = *

Added: incubator/openjpa/trunk/openjpa-lib/main/java/org/apache/openjpa/lib/util/concurrent/TimeUnit.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-lib/main/java/org/apache/openjpa/lib/util/concurrent/TimeUnit.java?rev=417856&view=auto
==============================================================================
--- incubator/openjpa/trunk/openjpa-lib/main/java/org/apache/openjpa/lib/util/concurrent/TimeUnit.java (added)
+++ incubator/openjpa/trunk/openjpa-lib/main/java/org/apache/openjpa/lib/util/concurrent/TimeUnit.java Wed Jun 28 12:34:33 2006
@@ -0,0 +1,564 @@
+/*
+ * Copyright 2006 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/licenses/publicdomain
+ */
+package org.apache.openjpa.lib.util.concurrent;
+
+
+/**
+ * A <tt>TimeUnit</tt> represents time durations at a given unit of
+ * granularity and provides utility methods to convert across units,
+ * and to perform timing and delay operations in these units.  A
+ * <tt>TimeUnit</tt> does not maintain time information, but only
+ * helps organize and use time representations that may be maintained
+ * separately across various contexts.  A nanosecond is defined as one
+ * thousandth of a microsecond, a microsecond as one thousandth of a
+ * millisecond, a millisecond as one thousandth of a second, a minute
+ * as sixty seconds, an hour as sixty minutes, and a day as twenty four
+ * hours.
+ *
+ * <p>A <tt>TimeUnit</tt> is mainly used to inform time-based methods
+ * how a given timing parameter should be interpreted. For example,
+ * the following code will timeout in 50 milliseconds if the {@link
+ * edu.emory.mathcs.backport.java.util.concurrent.locks.Lock lock} is not
+ * available:
+ *
+ * <pre>
+ * Lock lock = ...;
+ * if ( lock.tryLock(50L, TimeUnit.MILLISECONDS) ) ...
+ * </pre>
+ * while this code will timeout in 50 seconds:
+ * <pre>
+ * Lock lock = ...;
+ * if ( lock.tryLock(50L, TimeUnit.SECONDS) ) ...
+ * </pre>
+ *
+ * Note however, that there is no guarantee that a particular timeout
+ * implementation will be able to notice the passage of time at the
+ * same granularity as the given <tt>TimeUnit</tt>.
+ *
+ * @since 1.5
+ * @author Doug Lea
+ */
+public abstract class TimeUnit implements java.io.Serializable {
+    public static final TimeUnit NANOSECONDS = new TimeUnit(0, "NANOSECONDS") {
+            private final static long serialVersionUID = 535148490883208361L;
+
+            public long toNanos(long d) {
+                return d;
+            }
+
+            public long toMicros(long d) {
+                return d / (C1 / C0);
+            }
+
+            public long toMillis(long d) {
+                return d / (C2 / C0);
+            }
+
+            public long toSeconds(long d) {
+                return d / (C3 / C0);
+            }
+
+            public long toMinutes(long d) {
+                return d / (C4 / C0);
+            }
+
+            public long toHours(long d) {
+                return d / (C5 / C0);
+            }
+
+            public long toDays(long d) {
+                return d / (C6 / C0);
+            }
+
+            public long convert(long d, TimeUnit u) {
+                return u.toNanos(d);
+            }
+
+            int excessNanos(long d, long m) {
+                return (int) (d - (m * C2));
+            }
+        };
+
+    public static final TimeUnit MICROSECONDS = new TimeUnit(1, "MICROSECONDS") {
+            private final static long serialVersionUID = 2185906575929579108L;
+
+            public long toNanos(long d) {
+                return x(d, C1 / C0, MAX / (C1 / C0));
+            }
+
+            public long toMicros(long d) {
+                return d;
+            }
+
+            public long toMillis(long d) {
+                return d / (C2 / C1);
+            }
+
+            public long toSeconds(long d) {
+                return d / (C3 / C1);
+            }
+
+            public long toMinutes(long d) {
+                return d / (C4 / C1);
+            }
+
+            public long toHours(long d) {
+                return d / (C5 / C1);
+            }
+
+            public long toDays(long d) {
+                return d / (C6 / C1);
+            }
+
+            public long convert(long d, TimeUnit u) {
+                return u.toMicros(d);
+            }
+
+            int excessNanos(long d, long m) {
+                return (int) ((d * C1) - (m * C2));
+            }
+        };
+
+    public static final TimeUnit MILLISECONDS = new TimeUnit(2, "MILLISECONDS") {
+            private final static long serialVersionUID = 9032047794123325184L;
+
+            public long toNanos(long d) {
+                return x(d, C2 / C0, MAX / (C2 / C0));
+            }
+
+            public long toMicros(long d) {
+                return x(d, C2 / C1, MAX / (C2 / C1));
+            }
+
+            public long toMillis(long d) {
+                return d;
+            }
+
+            public long toSeconds(long d) {
+                return d / (C3 / C2);
+            }
+
+            public long toMinutes(long d) {
+                return d / (C4 / C2);
+            }
+
+            public long toHours(long d) {
+                return d / (C5 / C2);
+            }
+
+            public long toDays(long d) {
+                return d / (C6 / C2);
+            }
+
+            public long convert(long d, TimeUnit u) {
+                return u.toMillis(d);
+            }
+
+            int excessNanos(long d, long m) {
+                return 0;
+            }
+        };
+
+    public static final TimeUnit SECONDS = new TimeUnit(3, "SECONDS") {
+            private final static long serialVersionUID = 227755028449378390L;
+
+            public long toNanos(long d) {
+                return x(d, C3 / C0, MAX / (C3 / C0));
+            }
+
+            public long toMicros(long d) {
+                return x(d, C3 / C1, MAX / (C3 / C1));
+            }
+
+            public long toMillis(long d) {
+                return x(d, C3 / C2, MAX / (C3 / C2));
+            }
+
+            public long toSeconds(long d) {
+                return d;
+            }
+
+            public long toMinutes(long d) {
+                return d / (C4 / C3);
+            }
+
+            public long toHours(long d) {
+                return d / (C5 / C3);
+            }
+
+            public long toDays(long d) {
+                return d / (C6 / C3);
+            }
+
+            public long convert(long d, TimeUnit u) {
+                return u.toSeconds(d);
+            }
+
+            int excessNanos(long d, long m) {
+                return 0;
+            }
+        };
+
+    public static final TimeUnit MINUTES = new TimeUnit(4, "MINUTES") {
+            private final static long serialVersionUID = 1827351566402609187L;
+
+            public long toNanos(long d) {
+                return x(d, C4 / C0, MAX / (C4 / C0));
+            }
+
+            public long toMicros(long d) {
+                return x(d, C4 / C1, MAX / (C4 / C1));
+            }
+
+            public long toMillis(long d) {
+                return x(d, C4 / C2, MAX / (C4 / C2));
+            }
+
+            public long toSeconds(long d) {
+                return x(d, C4 / C3, MAX / (C4 / C3));
+            }
+
+            public long toMinutes(long d) {
+                return d;
+            }
+
+            public long toHours(long d) {
+                return d / (C5 / C4);
+            }
+
+            public long toDays(long d) {
+                return d / (C6 / C4);
+            }
+
+            public long convert(long d, TimeUnit u) {
+                return u.toMinutes(d);
+            }
+
+            int excessNanos(long d, long m) {
+                return 0;
+            }
+        };
+
+    public static final TimeUnit HOURS = new TimeUnit(5, "HOURS") {
+            private final static long serialVersionUID = -6438436134732089810L;
+
+            public long toNanos(long d) {
+                return x(d, C5 / C0, MAX / (C5 / C0));
+            }
+
+            public long toMicros(long d) {
+                return x(d, C5 / C1, MAX / (C5 / C1));
+            }
+
+            public long toMillis(long d) {
+                return x(d, C5 / C2, MAX / (C5 / C2));
+            }
+
+            public long toSeconds(long d) {
+                return x(d, C5 / C3, MAX / (C5 / C3));
+            }
+
+            public long toMinutes(long d) {
+                return x(d, C5 / C4, MAX / (C5 / C4));
+            }
+
+            public long toHours(long d) {
+                return d;
+            }
+
+            public long toDays(long d) {
+                return d / (C6 / C5);
+            }
+
+            public long convert(long d, TimeUnit u) {
+                return u.toHours(d);
+            }
+
+            int excessNanos(long d, long m) {
+                return 0;
+            }
+        };
+
+    public static final TimeUnit DAYS = new TimeUnit(6, "DAYS") {
+            private final static long serialVersionUID = 567463171959674600L;
+
+            public long toNanos(long d) {
+                return x(d, C6 / C0, MAX / (C6 / C0));
+            }
+
+            public long toMicros(long d) {
+                return x(d, C6 / C1, MAX / (C6 / C1));
+            }
+
+            public long toMillis(long d) {
+                return x(d, C6 / C2, MAX / (C6 / C2));
+            }
+
+            public long toSeconds(long d) {
+                return x(d, C6 / C3, MAX / (C6 / C3));
+            }
+
+            public long toMinutes(long d) {
+                return x(d, C6 / C4, MAX / (C6 / C4));
+            }
+
+            public long toHours(long d) {
+                return x(d, C6 / C5, MAX / (C6 / C5));
+            }
+
+            public long toDays(long d) {
+                return d;
+            }
+
+            public long convert(long d, TimeUnit u) {
+                return u.toDays(d);
+            }
+
+            int excessNanos(long d, long m) {
+                return 0;
+            }
+        };
+
+    private static final TimeUnit[] values = new TimeUnit[] {
+            NANOSECONDS, MICROSECONDS, MILLISECONDS, SECONDS, MINUTES, HOURS,
+            DAYS
+        };
+
+    // Handy constants for conversion methods
+    static final long C0 = 1;
+    static final long C1 = C0 * 1000;
+    static final long C2 = C1 * 1000;
+    static final long C3 = C2 * 1000;
+    static final long C4 = C3 * 60;
+    static final long C5 = C4 * 60;
+    static final long C6 = C5 * 24;
+    static final long MAX = Long.MAX_VALUE;
+
+    /**
+     * The index of this unit. This value is no longer used in this
+     * version of this class, but is retained for serialization
+     * compatibility with previous version.
+     */
+    private final int index;
+
+    /** name of this unit */
+    private final String name;
+
+    /** Internal constructor */
+    TimeUnit(int index, String name) {
+        this.index = index;
+        this.name = name;
+    }
+
+    public static TimeUnit[] values() {
+        return (TimeUnit[]) values.clone();
+    }
+
+    /**
+     * Scale d by m, checking for overflow.
+     * This has a short name to make above code more readable.
+     */
+    static long x(long d, long m, long over) {
+        if (d > over) {
+            return Long.MAX_VALUE;
+        }
+
+        if (d < -over) {
+            return Long.MIN_VALUE;
+        }
+
+        return d * m;
+    }
+
+    /**
+     * Convert the given time duration in the given unit to this
+     * unit.  Conversions from finer to coarser granularities
+     * truncate, so lose precision. For example converting
+     * <tt>999</tt> milliseconds to seconds results in
+     * <tt>0</tt>. Conversions from coarser to finer granularities
+     * with arguments that would numerically overflow saturate to
+     * <tt>Long.MIN_VALUE</tt> if negative or <tt>Long.MAX_VALUE</tt>
+     * if positive.
+     *
+     * <p>For example, to convert 10 minutes to milliseconds, use:
+     * <tt>TimeUnit.MILLISECONDS.convert(10L, TimeUnit.MINUTES)</tt>
+     *
+     * @param sourceDuration the time duration in the given <tt>sourceUnit</tt>
+     * @param sourceUnit the unit of the <tt>sourceDuration</tt> argument
+     * @return the converted duration in this unit,
+     * or <tt>Long.MIN_VALUE</tt> if conversion would negatively
+     * overflow, or <tt>Long.MAX_VALUE</tt> if it would positively overflow.
+     */
+    public abstract long convert(long sourceDuration, TimeUnit sourceUnit);
+
+    /**
+     * Equivalent to <tt>NANOSECONDS.convert(duration, this)</tt>.
+     * @param duration the duration
+     * @return the converted duration,
+     * or <tt>Long.MIN_VALUE</tt> if conversion would negatively
+     * overflow, or <tt>Long.MAX_VALUE</tt> if it would positively overflow.
+     * @see #convert
+     */
+    public abstract long toNanos(long duration);
+
+    /**
+     * Equivalent to <tt>MICROSECONDS.convert(duration, this)</tt>.
+     * @param duration the duration
+     * @return the converted duration,
+     * or <tt>Long.MIN_VALUE</tt> if conversion would negatively
+     * overflow, or <tt>Long.MAX_VALUE</tt> if it would positively overflow.
+     * @see #convert
+     */
+    public abstract long toMicros(long duration);
+
+    /**
+     * Equivalent to <tt>MILLISECONDS.convert(duration, this)</tt>.
+     * @param duration the duration
+     * @return the converted duration,
+     * or <tt>Long.MIN_VALUE</tt> if conversion would negatively
+     * overflow, or <tt>Long.MAX_VALUE</tt> if it would positively overflow.
+     * @see #convert
+     */
+    public abstract long toMillis(long duration);
+
+    /**
+     * Equivalent to <tt>SECONDS.convert(duration, this)</tt>.
+     * @param duration the duration
+     * @return the converted duration,
+     * or <tt>Long.MIN_VALUE</tt> if conversion would negatively
+     * overflow, or <tt>Long.MAX_VALUE</tt> if it would positively overflow.
+     * @see #convert
+     */
+    public abstract long toSeconds(long duration);
+
+    /**
+     * Equivalent to <tt>MINUTES.convert(duration, this)</tt>.
+     * @param duration the duration
+     * @return the converted duration,
+     * or <tt>Long.MIN_VALUE</tt> if conversion would negatively
+     * overflow, or <tt>Long.MAX_VALUE</tt> if it would positively overflow.
+     * @see #convert
+     * @since 1.6
+     */
+    public abstract long toMinutes(long duration);
+
+    /**
+     * Equivalent to <tt>HOURS.convert(duration, this)</tt>.
+     * @param duration the duration
+     * @return the converted duration,
+     * or <tt>Long.MIN_VALUE</tt> if conversion would negatively
+     * overflow, or <tt>Long.MAX_VALUE</tt> if it would positively overflow.
+     * @see #convert
+     * @since 1.6
+     */
+    public abstract long toHours(long duration);
+
+    /**
+     * Equivalent to <tt>DAYS.convert(duration, this)</tt>.
+     * @param duration the duration
+     * @return the converted duration
+     * @see #convert
+     * @since 1.6
+     */
+    public abstract long toDays(long duration);
+
+    /**
+     * Utility to compute the excess-nanosecond argument to wait,
+     * sleep, join.
+     * @param d the duration
+     * @param m the number of milliseconds
+     * @return the number of nanoseconds
+     */
+    abstract int excessNanos(long d, long m);
+
+    /**
+     * Performs a timed <tt>Object.wait</tt> using this time unit.
+     * This is a convenience method that converts timeout arguments
+     * into the form required by the <tt>Object.wait</tt> method.
+     *
+     * <p>For example, you could implement a blocking <tt>poll</tt>
+     * method (see {@link BlockingQueue#poll BlockingQueue.poll})
+     * using:
+     *
+     * <pre>
+         * public synchronized Object poll(long timeout, TimeUnit unit)
+         *    throws InterruptedException {
+     *    while (empty) {
+     *      unit.timedWait(this, timeout);
+     *      ...
+     *    }
+     *  }</pre>
+     *
+     * @param obj the object to wait on
+     * @param timeout the maximum time to wait. If less than
+     * or equal to zero, do not wait at all.
+     * @throws InterruptedException if interrupted while waiting.
+     * @see java.lang.Object#wait(long, int)
+     */
+    public void timedWait(Object obj, long timeout) throws InterruptedException {
+        if (timeout > 0) {
+            long ms = toMillis(timeout);
+            int ns = excessNanos(timeout, ms);
+            obj.wait(ms, ns);
+        }
+    }
+
+    /**
+     * Performs a timed <tt>Thread.join</tt> using this time unit.
+     * This is a convenience method that converts time arguments into the
+     * form required by the <tt>Thread.join</tt> method.
+     * @param thread the thread to wait for
+     * @param timeout the maximum time to wait. If less than
+     * or equal to zero, do not wait at all.
+     * @throws InterruptedException if interrupted while waiting.
+     * @see java.lang.Thread#join(long, int)
+     */
+    public void timedJoin(Thread thread, long timeout)
+        throws InterruptedException {
+        if (timeout > 0) {
+            long ms = toMillis(timeout);
+            int ns = excessNanos(timeout, ms);
+            thread.join(ms, ns);
+        }
+    }
+
+    /**
+     * Performs a <tt>Thread.sleep</tt> using this unit.
+     * This is a convenience method that converts time arguments into the
+     * form required by the <tt>Thread.sleep</tt> method.
+     * @param timeout the maximum time to sleep. If less than
+     * or equal to zero, do not sleep at all.
+     * @throws InterruptedException if interrupted while sleeping.
+     * @see java.lang.Thread#sleep
+     */
+    public void sleep(long timeout) throws InterruptedException {
+        if (timeout > 0) {
+            long ms = toMillis(timeout);
+            int ns = excessNanos(timeout, ms);
+            Thread.sleep(ms, ns);
+        }
+    }
+
+    public String toString() {
+        return name;
+    }
+}

Propchange: incubator/openjpa/trunk/openjpa-lib/main/java/org/apache/openjpa/lib/util/concurrent/TimeUnit.java
------------------------------------------------------------------------------
    svn:executable = *

Added: incubator/openjpa/trunk/openjpa-lib/main/java/org/apache/openjpa/lib/util/concurrent/Utils.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-lib/main/java/org/apache/openjpa/lib/util/concurrent/Utils.java?rev=417856&view=auto
==============================================================================
--- incubator/openjpa/trunk/openjpa-lib/main/java/org/apache/openjpa/lib/util/concurrent/Utils.java (added)
+++ incubator/openjpa/trunk/openjpa-lib/main/java/org/apache/openjpa/lib/util/concurrent/Utils.java Wed Jun 28 12:34:33 2006
@@ -0,0 +1,386 @@
+/*
+ * Copyright 2006 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * Written by Dawid Kurzyniec, based on code written by Doug Lea with assistance
+ * from members of JCP JSR-166 Expert Group. Released to the public domain,
+ * as explained at http://creativecommons.org/licenses/publicdomain.
+ *
+ * Thanks to Craig Mattocks for suggesting to use <code>sun.misc.Perf</code>.
+ */
+package org.apache.openjpa.lib.util.concurrent;
+
+import java.lang.reflect.Array;
+
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+
+import java.util.Collection;
+import java.util.Iterator;
+
+
+/**
+ * <p>
+ * This class groups together the functionality of java.util.concurrent that
+ * cannot be fully and reliably implemented in backport, but for which some
+ * form of emulation is possible.
+ * <p>
+ * Currently, this class contains methods related to nanosecond-precision
+ * timing, particularly via the {@link #nanoTime} method. To measure time
+ * accurately, this method by default uses <code>java.sun.Perf</code> on
+ * JDK1.4.2 and it falls back to <code>System.currentTimeMillis</code>
+ * on earlier JDKs.
+ *
+ * @author Dawid Kurzyniec
+ * @version 1.0
+ */
+public final class Utils {
+    private final static NanoTimer nanoTimer;
+    private final static String providerProp = "edu.emory.mathcs.backport.java.util.concurrent.NanoTimerProvider";
+
+    static {
+        NanoTimer timer = null;
+
+        try {
+            String nanoTimerClassName = (String) AccessController.doPrivileged(new PrivilegedAction() {
+                        public Object run() {
+                            return System.getProperty(providerProp);
+                        }
+                    });
+
+            if (nanoTimerClassName != null) {
+                Class cls = Class.forName(nanoTimerClassName);
+                timer = (NanoTimer) cls.newInstance();
+            }
+        } catch (Exception e) {
+            System.err.println(
+                "WARNING: unable to load the system-property-defined " +
+                "nanotime provider; switching to the default");
+            e.printStackTrace();
+        }
+
+        if (timer == null) {
+            try {
+                timer = new SunPerfProvider();
+            } catch (Throwable e) {
+            }
+        }
+
+        if (timer == null) {
+            timer = new MillisProvider();
+        }
+
+        nanoTimer = timer;
+    }
+
+    private Utils() {
+    }
+
+    /**
+     * Returns the current value of the most precise available system timer,
+     * in nanoseconds. This method can only be used to measure elapsed time and
+     * is not related to any other notion of system or wall-clock time. The
+     * value returned represents nanoseconds since some fixed but arbitrary
+     * time (perhaps in the future, so values may be negative). This method
+     * provides nanosecond precision, but not necessarily nanosecond accuracy.
+     * No guarantees are made about how frequently values change. Differences
+     * in successive calls that span greater than approximately 292 years
+     * (2^63 nanoseconds) will not accurately compute elapsed time due to
+     * numerical overflow.
+     * <p>
+     * <em>Implementation note:</em>By default, this method uses
+     * <code>sun.misc.Perf</code> on Java 1.4.2, and falls back to
+     * System.currentTimeMillis() emulation on earlier JDKs. Custom
+     * timer can be provided via the system property
+     * <code>edu.emory.mathcs.backport.java.util.concurrent.NanoTimerProvider</code>.
+     * The value of the property should name a class implementing
+     * {@link NanoTimer} interface.
+     * <p>
+     * Note: on JDK 1.4.2, <code>sun.misc.Perf</code> timer seems to have
+     * resolution of the order of 1 microsecond, measured on Linux.
+     *
+     * @return The current value of the system timer, in nanoseconds.
+     */
+    public static long nanoTime() {
+        return nanoTimer.nanoTime();
+    }
+
+    /**
+     * Causes the current thread to wait until it is signalled or interrupted,
+     * or the specified waiting time elapses. This method originally appears
+     * in the {@link Condition} interface, but it was moved to here since it
+     * can only be emulated, with very little accuracy guarantees: the
+     * efficient implementation requires accurate nanosecond timer and native
+     * support for nanosecond-precision wait queues, which are not usually
+     * present in JVMs prior to 1.5. Loss of precision may cause total waiting
+     * times to be systematically shorter than specified when re-waits occur.
+     *
+     * <p>The lock associated with this condition is atomically
+     * released and the current thread becomes disabled for thread scheduling
+     * purposes and lies dormant until <em>one</em> of five things happens:
+     * <ul>
+     * <li>Some other thread invokes the {@link
+     * edu.emory.mathcs.backport.java.util.concurrent.locks.Condition#signal}
+     * method for this
+     * <tt>Condition</tt> and the current thread happens to be chosen as the
+     * thread to be awakened; or
+     * <li>Some other thread invokes the {@link
+     * edu.emory.mathcs.backport.java.util.concurrent.locks.Condition#signalAll}
+     * method for this
+     * <tt>Condition</tt>; or
+     * <li>Some other thread {@link Thread#interrupt interrupts} the current
+     * thread, and interruption of thread suspension is supported; or
+     * <li>The specified waiting time elapses; or
+     * <li>A &quot;<em>spurious wakeup</em>&quot; occurs.
+     * </ul>
+     *
+     * <p>In all cases, before this method can return the current thread must
+     * re-acquire the lock associated with this condition. When the
+     * thread returns it is <em>guaranteed</em> to hold this lock.
+     *
+     * <p>If the current thread:
+     * <ul>
+     * <li>has its interrupted status set on entry to this method; or
+     * <li>is {@link Thread#interrupt interrupted} while waiting
+     * and interruption of thread suspension is supported,
+     * </ul>
+     * then {@link InterruptedException} is thrown and the current thread's
+     * interrupted status is cleared. It is not specified, in the first
+     * case, whether or not the test for interruption occurs before the lock
+     * is released.
+     *
+     * <p>The method returns an estimate of the number of nanoseconds
+     * remaining to wait given the supplied <tt>nanosTimeout</tt>
+     * value upon return, or a value less than or equal to zero if it
+     * timed out. Accuracy of this estimate is directly dependent on the
+     * accuracy of {@link #nanoTime}. This value can be used to determine
+     * whether and how long to re-wait in cases where the wait returns but an
+     * awaited condition still does not hold. Typical uses of this method take
+     * the following form:
+     *
+     * <pre>
+     * synchronized boolean aMethod(long timeout, TimeUnit unit) {
+     *   long nanosTimeout = unit.toNanos(timeout);
+     *   while (!conditionBeingWaitedFor) {
+     *     if (nanosTimeout &gt; 0)
+     *         nanosTimeout = theCondition.awaitNanos(nanosTimeout);
+     *      else
+     *        return false;
+     *   }
+     *   // ...
+     * }
+     * </pre>
+     *
+     * <p><b>Implementation Considerations</b>
+     * <p>The current thread is assumed to hold the lock associated with this
+     * <tt>Condition</tt> when this method is called.
+     * It is up to the implementation to determine if this is
+     * the case and if not, how to respond. Typically, an exception will be
+     * thrown (such as {@link IllegalMonitorStateException}) and the
+     * implementation must document that fact.
+     *
+     * <p>A condition implementation can favor responding to an interrupt over
+     * normal method return in response to a signal, or over indicating the
+     * elapse of the specified waiting time. In either case the implementation
+     * must ensure that the signal is redirected to another waiting thread, if
+     * there is one.
+     *
+     * @param cond the condition to wait for
+     * @param nanosTimeout the maximum time to wait, in nanoseconds
+     * @return A value less than or equal to zero if the wait has
+     * timed out; otherwise an estimate, that
+     * is strictly less than the <tt>nanosTimeout</tt> argument,
+     * of the time still remaining when this method returned.
+     *
+     * @throws InterruptedException if the current thread is interrupted (and
+     * interruption of thread suspension is supported).
+     */
+    public static long awaitNanos(Condition cond, long nanosTimeout)
+        throws InterruptedException {
+        if (nanosTimeout <= 0) {
+            return nanosTimeout;
+        }
+
+        long now = nanoTime();
+        cond.await(nanosTimeout, TimeUnit.NANOSECONDS);
+
+        return nanosTimeout - (nanoTime() - now);
+    }
+
+    private static long gcd(long a, long b) {
+        long r;
+
+        while (b > 0) {
+            r = a % b;
+            a = b;
+            b = r;
+        }
+
+        return a;
+    }
+
+    public static Object[] collectionToArray(Collection c) {
+        // guess the array size; expect to possibly be different
+        int len = c.size();
+        Object[] arr = new Object[len];
+        Iterator itr = c.iterator();
+        int idx = 0;
+
+        while (true) {
+            while ((idx < len) && itr.hasNext()) {
+                arr[idx++] = itr.next();
+            }
+
+            if (!itr.hasNext()) {
+                if (idx == len) {
+                    return arr;
+                }
+
+                // otherwise have to trim
+                return Arrays.copyOf(arr, idx, Object[].class);
+            }
+
+            // otherwise, have to grow
+            int newcap = ((arr.length / 2) + 1) * 3;
+
+            if (newcap < arr.length) {
+                // overflow
+                if (arr.length < Integer.MAX_VALUE) {
+                    newcap = Integer.MAX_VALUE;
+                } else {
+                    throw new OutOfMemoryError("required array size too large");
+                }
+            }
+
+            arr = Arrays.copyOf(arr, newcap, Object[].class);
+            len = newcap;
+        }
+    }
+
+    public static Object[] collectionToArray(Collection c, Object[] a) {
+        Class aType = a.getClass();
+
+        // guess the array size; expect to possibly be different
+        int len = c.size();
+        Object[] arr = ((a.length >= len) ? a
+                                          : (Object[]) Array.newInstance(aType.getComponentType(),
+                len));
+        Iterator itr = c.iterator();
+        int idx = 0;
+
+        while (true) {
+            while ((idx < len) && itr.hasNext()) {
+                arr[idx++] = itr.next();
+            }
+
+            if (!itr.hasNext()) {
+                if (idx == len) {
+                    return arr;
+                }
+
+                if (arr == a) {
+                    // orig array -> null terminate
+                    a[idx] = null;
+
+                    return a;
+                } else {
+                    // have to trim
+                    return Arrays.copyOf(arr, idx, aType);
+                }
+            }
+
+            // otherwise, have to grow
+            int newcap = ((arr.length / 2) + 1) * 3;
+
+            if (newcap < arr.length) {
+                // overflow
+                if (arr.length < Integer.MAX_VALUE) {
+                    newcap = Integer.MAX_VALUE;
+                } else {
+                    throw new OutOfMemoryError("required array size too large");
+                }
+            }
+
+            arr = Arrays.copyOf(arr, newcap, aType);
+            len = newcap;
+        }
+    }
+
+    private static final class SunPerfProvider implements NanoTimer {
+        final sun.misc.Perf perf;
+        final long multiplier;
+        final long divisor;
+
+        SunPerfProvider() {
+            perf = (sun.misc.Perf) AccessController.doPrivileged(new PrivilegedAction() {
+                        public Object run() {
+                            return sun.misc.Perf.getPerf();
+                        }
+                    });
+
+            // trying to avoid BOTH overflow and rounding errors
+            long numerator = 1000000000;
+            long denominator = perf.highResFrequency();
+            long gcd = gcd(numerator, denominator);
+            this.multiplier = numerator / gcd;
+            this.divisor = denominator / gcd;
+        }
+
+        public long nanoTime() {
+            long ctr = perf.highResCounter();
+
+            // anything less sophisticated suffers either from rounding errors
+            // (FP arithmetics, backport v1.0) or overflow, when gcd is small
+            // (a bug in backport v1.0_01 reported by Ramesh Nethi)
+            return ((ctr / divisor) * multiplier) +
+            (((ctr % divisor) * multiplier) / divisor);
+
+            // even the above can theoretically cause problems if your JVM is
+            // running for sufficiently long time, but "sufficiently" means 292
+            // years (worst case), or 30,000 years (common case).
+
+            // Details: when the ticks ctr overflows, there is no way to avoid
+            // discontinuity in computed nanos, even in infinite arithmetics,
+            // unless we count number of overflows that the ctr went through
+            // since the JVM started. This follows from the fact that
+            // (2^64*multiplier/divisor) mod (2^64) > 0 in general case.
+            // Theoretically we could find out the number of overflows by
+            // checking System.currentTimeMillis(), but this is unreliable
+            // since the system time can unpredictably change during the JVM
+            // lifetime.
+            // The time to overflow is 2^63 / ticks frequency. With current
+            // ticks frequencies of several MHz, it gives about 30,000 years
+            // before the problem happens. If ticks frequency reaches 1 GHz, the
+            // time to overflow is 292 years. It is unlikely that the frequency
+            // ever exceeds 1 GHz. We could double the time to overflow
+            // (to 2^64 / frequency) by using unsigned arithmetics, e.g. by
+            // adding the following correction whenever the ticks is negative:
+            //      -2*((Long.MIN_VALUE / divisor) * multiplier +
+            //          (Long.MIN_VALUE % divisor) * multiplier / divisor)
+            // But, with the worst case of as much as 292 years, it does not
+            // seem justified.
+        }
+    }
+
+    private static final class MillisProvider implements NanoTimer {
+        MillisProvider() {
+        }
+
+        public long nanoTime() {
+            return System.currentTimeMillis() * 1000000;
+        }
+    }
+}

Propchange: incubator/openjpa/trunk/openjpa-lib/main/java/org/apache/openjpa/lib/util/concurrent/Utils.java
------------------------------------------------------------------------------
    svn:executable = *

Added: incubator/openjpa/trunk/openjpa-lib/main/java/org/apache/openjpa/lib/util/concurrent/WaitQueue.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-lib/main/java/org/apache/openjpa/lib/util/concurrent/WaitQueue.java?rev=417856&view=auto
==============================================================================
--- incubator/openjpa/trunk/openjpa-lib/main/java/org/apache/openjpa/lib/util/concurrent/WaitQueue.java (added)
+++ incubator/openjpa/trunk/openjpa-lib/main/java/org/apache/openjpa/lib/util/concurrent/WaitQueue.java Wed Jun 28 12:34:33 2006
@@ -0,0 +1,162 @@
+/*
+ * Copyright 2006 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * Originally written by Doug Lea and released into the public domain.
+ * This may be used for any purposes whatsoever without acknowledgment.
+ * Thanks for the assistance and support of Sun Microsystems Labs,
+ * and everyone contributing, testing, and using this code.
+ */
+package org.apache.openjpa.lib.util.concurrent;
+
+import java.util.*;
+
+
+/**
+ * Base class for internal queue classes for semaphores, etc.
+ * Relies on subclasses to actually implement queue mechanics.
+ * NOTE: this class is NOT present in java.util.concurrent.
+ */
+public abstract class WaitQueue {
+    public abstract void insert(WaitNode w); // assumed not to block
+
+    public abstract WaitNode extract(); // should return null if empty
+
+    public abstract boolean hasNodes();
+
+    public abstract int getLength();
+
+    public abstract Collection getWaitingThreads();
+
+    public abstract boolean isWaiting(Thread thread);
+
+    public static interface QueuedSync {
+        // invoked with sync on wait node, (atomically) just before enqueuing
+        boolean recheck(WaitNode node);
+
+        // invoked with sync on wait node, (atomically) just before signalling
+        void takeOver(WaitNode node);
+    }
+
+    public static class WaitNode {
+        boolean waiting = true;
+        WaitNode next = null;
+        final Thread owner;
+
+        public WaitNode() {
+            this.owner = Thread.currentThread();
+        }
+
+        public Thread getOwner() {
+            return owner;
+        }
+
+        public synchronized boolean signal(QueuedSync sync) {
+            boolean signalled = waiting;
+
+            if (signalled) {
+                waiting = false;
+                notify();
+                sync.takeOver(this);
+            }
+
+            return signalled;
+        }
+
+        public synchronized boolean doTimedWait(QueuedSync sync, long nanos)
+            throws InterruptedException {
+            if (sync.recheck(this) || !waiting) {
+                return true;
+            } else if (nanos <= 0) {
+                waiting = false;
+
+                return false;
+            } else {
+                long deadline = Utils.nanoTime() + nanos;
+
+                try {
+                    for (;;) {
+                        TimeUnit.NANOSECONDS.timedWait(this, nanos);
+
+                        if (!waiting) { // definitely signalled
+
+                            return true;
+                        } else {
+                            nanos = deadline - Utils.nanoTime();
+
+                            if (nanos <= 0) { //  timed out
+                                waiting = false;
+
+                                return false;
+                            }
+                        }
+                    }
+                } catch (InterruptedException ex) {
+                    if (waiting) { // no notification
+                        waiting = false; // invalidate for the signaller
+                        throw ex;
+                    } else { // thread was interrupted after it was notified
+                        Thread.currentThread().interrupt();
+
+                        return true;
+                    }
+                }
+            }
+        }
+
+        public synchronized void doWait(QueuedSync sync)
+            throws InterruptedException {
+            if (!sync.recheck(this)) {
+                try {
+                    while (waiting)
+                        wait();
+                } catch (InterruptedException ex) {
+                    if (waiting) { // no notification
+                        waiting = false; // invalidate for the signaller
+                        throw ex;
+                    } else { // thread was interrupted after it was notified
+                        Thread.currentThread().interrupt();
+
+                        return;
+                    }
+                }
+            }
+        }
+
+        public synchronized void doWaitUninterruptibly(QueuedSync sync) {
+            if (!sync.recheck(this)) {
+                boolean wasInterrupted = Thread.interrupted();
+
+                try {
+                    while (waiting) {
+                        try {
+                            wait();
+                        } catch (InterruptedException ex) {
+                            wasInterrupted = true;
+
+                            // no need to notify; if we were signalled, we
+                            // must be not waiting, and we'll act like signalled
+                        }
+                    }
+                } finally {
+                    if (wasInterrupted) {
+                        Thread.currentThread().interrupt();
+                    }
+                }
+            }
+        }
+    }
+}

Propchange: incubator/openjpa/trunk/openjpa-lib/main/java/org/apache/openjpa/lib/util/concurrent/WaitQueue.java
------------------------------------------------------------------------------
    svn:executable = *

Added: incubator/openjpa/trunk/openjpa-lib/main/java/org/apache/openjpa/lib/util/concurrent/package.html
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-lib/main/java/org/apache/openjpa/lib/util/concurrent/package.html?rev=417856&view=auto
==============================================================================
--- incubator/openjpa/trunk/openjpa-lib/main/java/org/apache/openjpa/lib/util/concurrent/package.html (added)
+++ incubator/openjpa/trunk/openjpa-lib/main/java/org/apache/openjpa/lib/util/concurrent/package.html Wed Jun 28 12:34:33 2006
@@ -0,0 +1,5 @@
+<html>
+<body>
+	<p><strong>Concurrent Utilities</strong></p>
+</body>
+</html>

Propchange: incubator/openjpa/trunk/openjpa-lib/main/java/org/apache/openjpa/lib/util/concurrent/package.html
------------------------------------------------------------------------------
    svn:executable = *

Modified: incubator/openjpa/trunk/openjpa-lib/main/java/org/apache/openjpa/lib/util/package.html
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-lib/main/java/org/apache/openjpa/lib/util/package.html?rev=417856&r1=415364&r2=417856&view=diff
==============================================================================
--- incubator/openjpa/trunk/openjpa-lib/main/java/org/apache/openjpa/lib/util/package.html (original)
+++ incubator/openjpa/trunk/openjpa-lib/main/java/org/apache/openjpa/lib/util/package.html Wed Jun 28 12:34:33 2006
@@ -1,18 +1,3 @@
-<!--
-  Copyright 2006 The Apache Software Foundation.
-
-  Licensed under the Apache License, Version 2.0 (the "License");
-  you may not use this file except in compliance with the License.
-  You may obtain a copy of the License at
-
-     http://www.apache.org/licenses/LICENSE-2.0
-
-  Unless required by applicable law or agreed to in writing, software
-  distributed under the License is distributed on an "AS IS" BASIS,
-  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  See the License for the specific language governing permissions and
-  limitations under the License.
--->
 <html>
 <body>
 	<p><strong>General Utilities</strong></p>



Mime
View raw message