ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/main/java/util/concurrent/Exchanger.java
(Generate patch)

Comparing jsr166/src/main/java/util/concurrent/Exchanger.java (file contents):
Revision 1.31 by jsr166, Sun Nov 6 21:34:52 2005 UTC vs.
Revision 1.32 by dl, Sat Dec 10 20:09:28 2005 UTC

# Line 111 | Line 111 | public class Exchanger<V> {
111       * http://hdl.handle.net/1802/2104
112       */
113  
114 +    /** The number of CPUs, for sizing and spin control */
115 +    static final int NCPUS = Runtime.getRuntime().availableProcessors();
116 +
117      /**
118       * Size of collision space. Using a size of half the number of
119       * CPUs provides enough space for threads to find each other but
# Line 118 | Line 121 | public class Exchanger<V> {
121       * out to become unstuck. Note that the arena array holds SIZE+1
122       * elements, to include the top-of-stack slot.
123       */
124 <    private static final int SIZE =
125 <        (Runtime.getRuntime().availableProcessors() + 1) / 2;
124 >    private static final int SIZE = (NCPUS + 1) / 2;
125 >
126 >    /**
127 >     * The number of times to spin before blocking in timed waits.
128 >     * The value is empirically derived -- it works well across a
129 >     * variety of processors and OSes. Empirically, the best value
130 >     * seems not to vary with number of CPUs (beyond 2) so is just
131 >     * a constant.
132 >     */
133 >    static final int maxTimedSpins = (NCPUS < 2)? 0 : 16;
134 >
135 >    /**
136 >     * The number of times to spin before blocking in untimed waits.
137 >     * This is greater than timed value because untimed waits spin
138 >     * faster since they don't need to check times on each spin.
139 >     */
140 >    static final int maxUntimedSpins = maxTimedSpins * 32;
141 >
142 >    /**
143 >     * The number of nanoseconds for which it is faster to spin
144 >     * rather than to use timed park. A rough estimate suffices.
145 >     */
146 >    static final long spinForTimeoutThreshold = 1000L;
147  
148      /**
149       * Base unit in nanoseconds for backoffs. Must be a power of two.
# Line 271 | Line 295 | public class Exchanger<V> {
295           */
296          Object waitForHole(boolean timed, long nanos) {
297              long lastTime = timed ? System.nanoTime() : 0;
298 +            int spins = timed? maxTimedSpins : maxUntimedSpins;
299              Object h;
300              while ((h = get()) == null) {
301                  // If interrupted or timed out, try to cancel by
# Line 279 | Line 304 | public class Exchanger<V> {
304                      (timed && nanos <= 0)) {
305                      if (compareAndSet(null, FAIL))
306                          return FAIL;
307 <                }
308 <                else if (!timed)
309 <                    LockSupport.park();
310 <                else {
311 <                    LockSupport.parkNanos(nanos);
312 <                    long now = System.nanoTime();
313 <                    nanos -= now - lastTime;
314 <                    lastTime = now;
307 >                } else {
308 >                    if (timed) {
309 >                        long now = System.nanoTime();
310 >                        nanos -= now - lastTime;
311 >                        lastTime = now;
312 >                    }
313 >                    if (spins > 0)
314 >                        --spins;
315 >                    else if (!timed)
316 >                        LockSupport.park();
317 >                    else if (nanos > spinForTimeoutThreshold)
318 >                        LockSupport.parkNanos(nanos);
319                  }
320              }
321              return h;

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines