jdk/src/java.base/share/classes/java/util/concurrent/Exchanger.java
author dl
Fri, 03 Mar 2017 10:45:38 -0800
changeset 44039 058585425bb7
parent 39781 8190c004acbd
permissions -rw-r--r--
8173909: Miscellaneous changes imported from jsr166 CVS 2017-03 Reviewed-by: martin, psandoz
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
     1
/*
90ce3da70b43 Initial load
duke
parents:
diff changeset
     2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
90ce3da70b43 Initial load
duke
parents:
diff changeset
     3
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
     4
 * This code is free software; you can redistribute it and/or modify it
90ce3da70b43 Initial load
duke
parents:
diff changeset
     5
 * under the terms of the GNU General Public License version 2 only, as
5506
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 2
diff changeset
     6
 * published by the Free Software Foundation.  Oracle designates this
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
     7
 * particular file as subject to the "Classpath" exception as provided
5506
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 2
diff changeset
     8
 * by Oracle in the LICENSE file that accompanied this code.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
     9
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    10
 * This code is distributed in the hope that it will be useful, but WITHOUT
90ce3da70b43 Initial load
duke
parents:
diff changeset
    11
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
90ce3da70b43 Initial load
duke
parents:
diff changeset
    12
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
90ce3da70b43 Initial load
duke
parents:
diff changeset
    13
 * version 2 for more details (a copy is included in the LICENSE file that
90ce3da70b43 Initial load
duke
parents:
diff changeset
    14
 * accompanied this code).
90ce3da70b43 Initial load
duke
parents:
diff changeset
    15
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    16
 * You should have received a copy of the GNU General Public License version
90ce3da70b43 Initial load
duke
parents:
diff changeset
    17
 * 2 along with this work; if not, write to the Free Software Foundation,
90ce3da70b43 Initial load
duke
parents:
diff changeset
    18
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    19
 *
5506
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 2
diff changeset
    20
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 2
diff changeset
    21
 * or visit www.oracle.com if you need additional information or have any
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 2
diff changeset
    22
 * questions.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    23
 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    24
90ce3da70b43 Initial load
duke
parents:
diff changeset
    25
/*
90ce3da70b43 Initial load
duke
parents:
diff changeset
    26
 * This file is available under and governed by the GNU General Public
90ce3da70b43 Initial load
duke
parents:
diff changeset
    27
 * License version 2 only, as published by the Free Software Foundation.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    28
 * However, the following notice accompanied the original version of this
90ce3da70b43 Initial load
duke
parents:
diff changeset
    29
 * file:
90ce3da70b43 Initial load
duke
parents:
diff changeset
    30
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    31
 * Written by Doug Lea, Bill Scherer, and Michael Scott with
90ce3da70b43 Initial load
duke
parents:
diff changeset
    32
 * assistance from members of JCP JSR-166 Expert Group and released to
90ce3da70b43 Initial load
duke
parents:
diff changeset
    33
 * the public domain, as explained at
9242
ef138d47df58 7034657: Update Creative Commons license URL in legal notices
dl
parents: 8764
diff changeset
    34
 * http://creativecommons.org/publicdomain/zero/1.0/
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    35
 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    36
90ce3da70b43 Initial load
duke
parents:
diff changeset
    37
package java.util.concurrent;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    38
39725
9548f8d846e9 8080603: Replace Unsafe with VarHandle in java.util.concurrent classes
dl
parents: 36936
diff changeset
    39
import java.lang.invoke.MethodHandles;
9548f8d846e9 8080603: Replace Unsafe with VarHandle in java.util.concurrent classes
dl
parents: 36936
diff changeset
    40
import java.lang.invoke.VarHandle;
9548f8d846e9 8080603: Replace Unsafe with VarHandle in java.util.concurrent classes
dl
parents: 36936
diff changeset
    41
import java.util.concurrent.locks.LockSupport;
9548f8d846e9 8080603: Replace Unsafe with VarHandle in java.util.concurrent classes
dl
parents: 36936
diff changeset
    42
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    43
/**
90ce3da70b43 Initial load
duke
parents:
diff changeset
    44
 * A synchronization point at which threads can pair and swap elements
90ce3da70b43 Initial load
duke
parents:
diff changeset
    45
 * within pairs.  Each thread presents some object on entry to the
90ce3da70b43 Initial load
duke
parents:
diff changeset
    46
 * {@link #exchange exchange} method, matches with a partner thread,
90ce3da70b43 Initial load
duke
parents:
diff changeset
    47
 * and receives its partner's object on return.  An Exchanger may be
90ce3da70b43 Initial load
duke
parents:
diff changeset
    48
 * viewed as a bidirectional form of a {@link SynchronousQueue}.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    49
 * Exchangers may be useful in applications such as genetic algorithms
90ce3da70b43 Initial load
duke
parents:
diff changeset
    50
 * and pipeline designs.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    51
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    52
 * <p><b>Sample Usage:</b>
90ce3da70b43 Initial load
duke
parents:
diff changeset
    53
 * Here are the highlights of a class that uses an {@code Exchanger}
90ce3da70b43 Initial load
duke
parents:
diff changeset
    54
 * to swap buffers between threads so that the thread filling the
90ce3da70b43 Initial load
duke
parents:
diff changeset
    55
 * buffer gets a freshly emptied one when it needs it, handing off the
90ce3da70b43 Initial load
duke
parents:
diff changeset
    56
 * filled one to the thread emptying the buffer.
32991
b27c76b82713 8134853: Bulk integration of java.util.concurrent classes
dl
parents: 25859
diff changeset
    57
 * <pre> {@code
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    58
 * class FillAndEmpty {
32991
b27c76b82713 8134853: Bulk integration of java.util.concurrent classes
dl
parents: 25859
diff changeset
    59
 *   Exchanger<DataBuffer> exchanger = new Exchanger<>();
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    60
 *   DataBuffer initialEmptyBuffer = ... a made-up type
90ce3da70b43 Initial load
duke
parents:
diff changeset
    61
 *   DataBuffer initialFullBuffer = ...
90ce3da70b43 Initial load
duke
parents:
diff changeset
    62
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    63
 *   class FillingLoop implements Runnable {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    64
 *     public void run() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    65
 *       DataBuffer currentBuffer = initialEmptyBuffer;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    66
 *       try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    67
 *         while (currentBuffer != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    68
 *           addToBuffer(currentBuffer);
90ce3da70b43 Initial load
duke
parents:
diff changeset
    69
 *           if (currentBuffer.isFull())
90ce3da70b43 Initial load
duke
parents:
diff changeset
    70
 *             currentBuffer = exchanger.exchange(currentBuffer);
90ce3da70b43 Initial load
duke
parents:
diff changeset
    71
 *         }
90ce3da70b43 Initial load
duke
parents:
diff changeset
    72
 *       } catch (InterruptedException ex) { ... handle ... }
90ce3da70b43 Initial load
duke
parents:
diff changeset
    73
 *     }
90ce3da70b43 Initial load
duke
parents:
diff changeset
    74
 *   }
90ce3da70b43 Initial load
duke
parents:
diff changeset
    75
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    76
 *   class EmptyingLoop implements Runnable {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    77
 *     public void run() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    78
 *       DataBuffer currentBuffer = initialFullBuffer;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    79
 *       try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    80
 *         while (currentBuffer != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    81
 *           takeFromBuffer(currentBuffer);
90ce3da70b43 Initial load
duke
parents:
diff changeset
    82
 *           if (currentBuffer.isEmpty())
90ce3da70b43 Initial load
duke
parents:
diff changeset
    83
 *             currentBuffer = exchanger.exchange(currentBuffer);
90ce3da70b43 Initial load
duke
parents:
diff changeset
    84
 *         }
90ce3da70b43 Initial load
duke
parents:
diff changeset
    85
 *       } catch (InterruptedException ex) { ... handle ...}
90ce3da70b43 Initial load
duke
parents:
diff changeset
    86
 *     }
90ce3da70b43 Initial load
duke
parents:
diff changeset
    87
 *   }
90ce3da70b43 Initial load
duke
parents:
diff changeset
    88
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    89
 *   void start() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    90
 *     new Thread(new FillingLoop()).start();
90ce3da70b43 Initial load
duke
parents:
diff changeset
    91
 *     new Thread(new EmptyingLoop()).start();
90ce3da70b43 Initial load
duke
parents:
diff changeset
    92
 *   }
18768
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
    93
 * }}</pre>
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    94
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    95
 * <p>Memory consistency effects: For each pair of threads that
90ce3da70b43 Initial load
duke
parents:
diff changeset
    96
 * successfully exchange objects via an {@code Exchanger}, actions
90ce3da70b43 Initial load
duke
parents:
diff changeset
    97
 * prior to the {@code exchange()} in each thread
90ce3da70b43 Initial load
duke
parents:
diff changeset
    98
 * <a href="package-summary.html#MemoryVisibility"><i>happen-before</i></a>
90ce3da70b43 Initial load
duke
parents:
diff changeset
    99
 * those subsequent to a return from the corresponding {@code exchange()}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   100
 * in the other thread.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   101
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   102
 * @since 1.5
90ce3da70b43 Initial load
duke
parents:
diff changeset
   103
 * @author Doug Lea and Bill Scherer and Michael Scott
90ce3da70b43 Initial load
duke
parents:
diff changeset
   104
 * @param <V> The type of objects that may be exchanged
90ce3da70b43 Initial load
duke
parents:
diff changeset
   105
 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   106
public class Exchanger<V> {
18768
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   107
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   108
    /*
18768
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   109
     * Overview: The core algorithm is, for an exchange "slot",
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   110
     * and a participant (caller) with an item:
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   111
     *
18768
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   112
     * for (;;) {
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   113
     *   if (slot is empty) {                       // offer
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   114
     *     place item in a Node;
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   115
     *     if (can CAS slot from empty to node) {
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   116
     *       wait for release;
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   117
     *       return matching item in node;
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   118
     *     }
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   119
     *   }
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   120
     *   else if (can CAS slot from node to empty) { // release
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   121
     *     get the item in node;
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   122
     *     set matching item in node;
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   123
     *     release waiting thread;
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   124
     *   }
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   125
     *   // else retry on CAS failure
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   126
     * }
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   127
     *
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   128
     * This is among the simplest forms of a "dual data structure" --
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   129
     * see Scott and Scherer's DISC 04 paper and
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   130
     * http://www.cs.rochester.edu/research/synchronization/pseudocode/duals.html
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   131
     *
18768
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   132
     * This works great in principle. But in practice, like many
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   133
     * algorithms centered on atomic updates to a single location, it
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   134
     * scales horribly when there are more than a few participants
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   135
     * using the same Exchanger. So the implementation instead uses a
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   136
     * form of elimination arena, that spreads out this contention by
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   137
     * arranging that some threads typically use different slots,
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   138
     * while still ensuring that eventually, any two parties will be
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   139
     * able to exchange items. That is, we cannot completely partition
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   140
     * across threads, but instead give threads arena indices that
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   141
     * will on average grow under contention and shrink under lack of
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   142
     * contention. We approach this by defining the Nodes that we need
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   143
     * anyway as ThreadLocals, and include in them per-thread index
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   144
     * and related bookkeeping state. (We can safely reuse per-thread
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   145
     * nodes rather than creating them fresh each time because slots
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   146
     * alternate between pointing to a node vs null, so cannot
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   147
     * encounter ABA problems. However, we do need some care in
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   148
     * resetting them between uses.)
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   149
     *
18768
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   150
     * Implementing an effective arena requires allocating a bunch of
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   151
     * space, so we only do so upon detecting contention (except on
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   152
     * uniprocessors, where they wouldn't help, so aren't used).
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   153
     * Otherwise, exchanges use the single-slot slotExchange method.
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   154
     * On contention, not only must the slots be in different
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   155
     * locations, but the locations must not encounter memory
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   156
     * contention due to being on the same cache line (or more
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   157
     * generally, the same coherence unit).  Because, as of this
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   158
     * writing, there is no way to determine cacheline size, we define
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   159
     * a value that is enough for common platforms.  Additionally,
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   160
     * extra care elsewhere is taken to avoid other false/unintended
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   161
     * sharing and to enhance locality, including adding padding (via
39725
9548f8d846e9 8080603: Replace Unsafe with VarHandle in java.util.concurrent classes
dl
parents: 36936
diff changeset
   162
     * @Contended) to Nodes, embedding "bound" as an Exchanger field.
18768
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   163
     *
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   164
     * The arena starts out with only one used slot. We expand the
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   165
     * effective arena size by tracking collisions; i.e., failed CASes
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   166
     * while trying to exchange. By nature of the above algorithm, the
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   167
     * only kinds of collision that reliably indicate contention are
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   168
     * when two attempted releases collide -- one of two attempted
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   169
     * offers can legitimately fail to CAS without indicating
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   170
     * contention by more than one other thread. (Note: it is possible
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   171
     * but not worthwhile to more precisely detect contention by
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   172
     * reading slot values after CAS failures.)  When a thread has
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   173
     * collided at each slot within the current arena bound, it tries
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   174
     * to expand the arena size by one. We track collisions within
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   175
     * bounds by using a version (sequence) number on the "bound"
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   176
     * field, and conservatively reset collision counts when a
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   177
     * participant notices that bound has been updated (in either
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   178
     * direction).
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   179
     *
18768
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   180
     * The effective arena size is reduced (when there is more than
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   181
     * one slot) by giving up on waiting after a while and trying to
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   182
     * decrement the arena size on expiration. The value of "a while"
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   183
     * is an empirical matter.  We implement by piggybacking on the
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   184
     * use of spin->yield->block that is essential for reasonable
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   185
     * waiting performance anyway -- in a busy exchanger, offers are
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   186
     * usually almost immediately released, in which case context
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   187
     * switching on multiprocessors is extremely slow/wasteful.  Arena
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   188
     * waits just omit the blocking part, and instead cancel. The spin
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   189
     * count is empirically chosen to be a value that avoids blocking
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   190
     * 99% of the time under maximum sustained exchange rates on a
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   191
     * range of test machines. Spins and yields entail some limited
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   192
     * randomness (using a cheap xorshift) to avoid regular patterns
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   193
     * that can induce unproductive grow/shrink cycles. (Using a
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   194
     * pseudorandom also helps regularize spin cycle duration by
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   195
     * making branches unpredictable.)  Also, during an offer, a
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   196
     * waiter can "know" that it will be released when its slot has
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   197
     * changed, but cannot yet proceed until match is set.  In the
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   198
     * mean time it cannot cancel the offer, so instead spins/yields.
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   199
     * Note: It is possible to avoid this secondary check by changing
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   200
     * the linearization point to be a CAS of the match field (as done
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   201
     * in one case in the Scott & Scherer DISC paper), which also
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   202
     * increases asynchrony a bit, at the expense of poorer collision
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   203
     * detection and inability to always reuse per-thread nodes. So
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   204
     * the current scheme is typically a better tradeoff.
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   205
     *
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   206
     * On collisions, indices traverse the arena cyclically in reverse
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   207
     * order, restarting at the maximum index (which will tend to be
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   208
     * sparsest) when bounds change. (On expirations, indices instead
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   209
     * are halved until reaching 0.) It is possible (and has been
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   210
     * tried) to use randomized, prime-value-stepped, or double-hash
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   211
     * style traversal instead of simple cyclic traversal to reduce
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   212
     * bunching.  But empirically, whatever benefits these may have
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   213
     * don't overcome their added overhead: We are managing operations
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   214
     * that occur very quickly unless there is sustained contention,
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   215
     * so simpler/faster control policies work better than more
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   216
     * accurate but slower ones.
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   217
     *
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   218
     * Because we use expiration for arena size control, we cannot
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   219
     * throw TimeoutExceptions in the timed version of the public
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   220
     * exchange method until the arena size has shrunken to zero (or
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   221
     * the arena isn't enabled). This may delay response to timeout
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   222
     * but is still within spec.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   223
     *
18768
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   224
     * Essentially all of the implementation is in methods
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   225
     * slotExchange and arenaExchange. These have similar overall
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   226
     * structure, but differ in too many details to combine. The
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   227
     * slotExchange method uses the single Exchanger field "slot"
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   228
     * rather than arena array elements. However, it still needs
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   229
     * minimal collision detection to trigger arena construction.
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   230
     * (The messiest part is making sure interrupt status and
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   231
     * InterruptedExceptions come out right during transitions when
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   232
     * both methods may be called. This is done by using null return
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   233
     * as a sentinel to recheck interrupt status.)
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   234
     *
18768
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   235
     * As is too common in this sort of code, methods are monolithic
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   236
     * because most of the logic relies on reads of fields that are
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   237
     * maintained as local variables so can't be nicely factored --
39781
8190c004acbd 8161591: Miscellaneous changes imported from jsr166 CVS 2016-07
dl
parents: 39725
diff changeset
   238
     * mainly, here, bulky spin->yield->block/cancel code.  Note that
8190c004acbd 8161591: Miscellaneous changes imported from jsr166 CVS 2016-07
dl
parents: 39725
diff changeset
   239
     * field Node.item is not declared as volatile even though it is
8190c004acbd 8161591: Miscellaneous changes imported from jsr166 CVS 2016-07
dl
parents: 39725
diff changeset
   240
     * read by releasing threads, because they only do so after CAS
8190c004acbd 8161591: Miscellaneous changes imported from jsr166 CVS 2016-07
dl
parents: 39725
diff changeset
   241
     * operations that must precede access, and all uses by the owning
8190c004acbd 8161591: Miscellaneous changes imported from jsr166 CVS 2016-07
dl
parents: 39725
diff changeset
   242
     * thread are otherwise acceptably ordered by other operations.
8190c004acbd 8161591: Miscellaneous changes imported from jsr166 CVS 2016-07
dl
parents: 39725
diff changeset
   243
     * (Because the actual points of atomicity are slot CASes, it
8190c004acbd 8161591: Miscellaneous changes imported from jsr166 CVS 2016-07
dl
parents: 39725
diff changeset
   244
     * would also be legal for the write to Node.match in a release to
8190c004acbd 8161591: Miscellaneous changes imported from jsr166 CVS 2016-07
dl
parents: 39725
diff changeset
   245
     * be weaker than a full volatile write. However, this is not done
8190c004acbd 8161591: Miscellaneous changes imported from jsr166 CVS 2016-07
dl
parents: 39725
diff changeset
   246
     * because it could allow further postponement of the write,
8190c004acbd 8161591: Miscellaneous changes imported from jsr166 CVS 2016-07
dl
parents: 39725
diff changeset
   247
     * delaying progress.)
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   248
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   249
18768
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   250
    /**
39725
9548f8d846e9 8080603: Replace Unsafe with VarHandle in java.util.concurrent classes
dl
parents: 36936
diff changeset
   251
     * The index distance (as a shift value) between any two used slots
9548f8d846e9 8080603: Replace Unsafe with VarHandle in java.util.concurrent classes
dl
parents: 36936
diff changeset
   252
     * in the arena, spacing them out to avoid false sharing.
18768
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   253
     */
39725
9548f8d846e9 8080603: Replace Unsafe with VarHandle in java.util.concurrent classes
dl
parents: 36936
diff changeset
   254
    private static final int ASHIFT = 5;
18768
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   255
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   256
    /**
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   257
     * The maximum supported arena index. The maximum allocatable
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   258
     * arena size is MMASK + 1. Must be a power of two minus one, less
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   259
     * than (1<<(31-ASHIFT)). The cap of 255 (0xff) more than suffices
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   260
     * for the expected scaling limits of the main algorithms.
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   261
     */
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   262
    private static final int MMASK = 0xff;
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   263
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   264
    /**
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   265
     * Unit for sequence/version bits of bound field. Each successful
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   266
     * change to the bound also adds SEQ.
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   267
     */
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   268
    private static final int SEQ = MMASK + 1;
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   269
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   270
    /** The number of CPUs, for sizing and spin control */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   271
    private static final int NCPU = Runtime.getRuntime().availableProcessors();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   272
90ce3da70b43 Initial load
duke
parents:
diff changeset
   273
    /**
18768
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   274
     * The maximum slot index of the arena: The number of slots that
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   275
     * can in principle hold all threads without contention, or at
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   276
     * most the maximum indexable value.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   277
     */
18768
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   278
    static final int FULL = (NCPU >= (MMASK << 1)) ? MMASK : NCPU >>> 1;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   279
90ce3da70b43 Initial load
duke
parents:
diff changeset
   280
    /**
18768
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   281
     * The bound for spins while waiting for a match. The actual
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   282
     * number of iterations will on average be about twice this value
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   283
     * due to randomization. Note: Spinning is disabled when NCPU==1.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   284
     */
18768
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   285
    private static final int SPINS = 1 << 10;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   286
90ce3da70b43 Initial load
duke
parents:
diff changeset
   287
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   288
     * Value representing null arguments/returns from public
18768
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   289
     * methods. Needed because the API originally didn't disallow null
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   290
     * arguments, which it should have.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   291
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   292
    private static final Object NULL_ITEM = new Object();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   293
90ce3da70b43 Initial load
duke
parents:
diff changeset
   294
    /**
18768
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   295
     * Sentinel value returned by internal exchange methods upon
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   296
     * timeout, to avoid need for separate timed versions of these
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   297
     * methods.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   298
     */
18768
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   299
    private static final Object TIMED_OUT = new Object();
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   300
18768
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   301
    /**
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   302
     * Nodes hold partially exchanged data, plus other per-thread
35981
e3e89c0bb3d9 8145485: Miscellaneous changes imported from jsr166 CVS 2016-02
dl
parents: 34369
diff changeset
   303
     * bookkeeping. Padded via @Contended to reduce memory contention.
18768
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   304
     */
34369
b6df4cc80001 8140687: Move @Contended to the jdk.internal.vm.annotation package
chegar
parents: 33674
diff changeset
   305
    @jdk.internal.vm.annotation.Contended static final class Node {
18768
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   306
        int index;              // Arena index
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   307
        int bound;              // Last recorded value of Exchanger.bound
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   308
        int collides;           // Number of CAS failures at current bound
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   309
        int hash;               // Pseudo-random for spins
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   310
        Object item;            // This thread's current item
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   311
        volatile Object match;  // Item provided by releasing thread
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   312
        volatile Thread parked; // Set to this thread when parked, else null
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   313
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   314
18768
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   315
    /** The corresponding thread local class */
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   316
    static final class Participant extends ThreadLocal<Node> {
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   317
        public Node initialValue() { return new Node(); }
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   318
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   319
90ce3da70b43 Initial load
duke
parents:
diff changeset
   320
    /**
32991
b27c76b82713 8134853: Bulk integration of java.util.concurrent classes
dl
parents: 25859
diff changeset
   321
     * Per-thread state.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   322
     */
18768
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   323
    private final Participant participant;
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   324
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   325
    /**
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   326
     * Elimination array; null until enabled (within slotExchange).
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   327
     * Element accesses use emulation of volatile gets and CAS.
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   328
     */
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   329
    private volatile Node[] arena;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   330
90ce3da70b43 Initial load
duke
parents:
diff changeset
   331
    /**
18768
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   332
     * Slot used until contention detected.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   333
     */
18768
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   334
    private volatile Node slot;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   335
90ce3da70b43 Initial load
duke
parents:
diff changeset
   336
    /**
18768
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   337
     * The index of the largest valid arena position, OR'ed with SEQ
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   338
     * number in high bits, incremented on each update.  The initial
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   339
     * update from 0 to SEQ is used to ensure that the arena array is
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   340
     * constructed only once.
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   341
     */
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   342
    private volatile int bound;
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   343
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   344
    /**
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   345
     * Exchange function when arenas enabled. See above for explanation.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   346
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   347
     * @param item the (non-null) item to exchange
90ce3da70b43 Initial load
duke
parents:
diff changeset
   348
     * @param timed true if the wait is timed
18768
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   349
     * @param ns if timed, the maximum wait time, else 0L
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   350
     * @return the other thread's item; or null if interrupted; or
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   351
     * TIMED_OUT if timed and timed out
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   352
     */
18768
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   353
    private final Object arenaExchange(Object item, boolean timed, long ns) {
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   354
        Node[] a = arena;
39725
9548f8d846e9 8080603: Replace Unsafe with VarHandle in java.util.concurrent classes
dl
parents: 36936
diff changeset
   355
        int alen = a.length;
18768
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   356
        Node p = participant.get();
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   357
        for (int i = p.index;;) {                      // access slot at i
39725
9548f8d846e9 8080603: Replace Unsafe with VarHandle in java.util.concurrent classes
dl
parents: 36936
diff changeset
   358
            int b, m, c;
9548f8d846e9 8080603: Replace Unsafe with VarHandle in java.util.concurrent classes
dl
parents: 36936
diff changeset
   359
            int j = (i << ASHIFT) + ((1 << ASHIFT) - 1);
9548f8d846e9 8080603: Replace Unsafe with VarHandle in java.util.concurrent classes
dl
parents: 36936
diff changeset
   360
            if (j < 0 || j >= alen)
9548f8d846e9 8080603: Replace Unsafe with VarHandle in java.util.concurrent classes
dl
parents: 36936
diff changeset
   361
                j = alen - 1;
9548f8d846e9 8080603: Replace Unsafe with VarHandle in java.util.concurrent classes
dl
parents: 36936
diff changeset
   362
            Node q = (Node)AA.getAcquire(a, j);
9548f8d846e9 8080603: Replace Unsafe with VarHandle in java.util.concurrent classes
dl
parents: 36936
diff changeset
   363
            if (q != null && AA.compareAndSet(a, j, q, null)) {
18768
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   364
                Object v = q.item;                     // release
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   365
                q.match = item;
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   366
                Thread w = q.parked;
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   367
                if (w != null)
39725
9548f8d846e9 8080603: Replace Unsafe with VarHandle in java.util.concurrent classes
dl
parents: 36936
diff changeset
   368
                    LockSupport.unpark(w);
18768
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   369
                return v;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   370
            }
18768
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   371
            else if (i <= (m = (b = bound) & MMASK) && q == null) {
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   372
                p.item = item;                         // offer
39725
9548f8d846e9 8080603: Replace Unsafe with VarHandle in java.util.concurrent classes
dl
parents: 36936
diff changeset
   373
                if (AA.compareAndSet(a, j, null, p)) {
18768
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   374
                    long end = (timed && m == 0) ? System.nanoTime() + ns : 0L;
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   375
                    Thread t = Thread.currentThread(); // wait
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   376
                    for (int h = p.hash, spins = SPINS;;) {
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   377
                        Object v = p.match;
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   378
                        if (v != null) {
39725
9548f8d846e9 8080603: Replace Unsafe with VarHandle in java.util.concurrent classes
dl
parents: 36936
diff changeset
   379
                            MATCH.setRelease(p, null);
18768
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   380
                            p.item = null;             // clear for next use
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   381
                            p.hash = h;
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   382
                            return v;
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   383
                        }
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   384
                        else if (spins > 0) {
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   385
                            h ^= h << 1; h ^= h >>> 3; h ^= h << 10; // xorshift
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   386
                            if (h == 0)                // initialize hash
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   387
                                h = SPINS | (int)t.getId();
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   388
                            else if (h < 0 &&          // approx 50% true
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   389
                                     (--spins & ((SPINS >>> 1) - 1)) == 0)
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   390
                                Thread.yield();        // two yields per wait
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   391
                        }
39725
9548f8d846e9 8080603: Replace Unsafe with VarHandle in java.util.concurrent classes
dl
parents: 36936
diff changeset
   392
                        else if (AA.getAcquire(a, j) != p)
18768
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   393
                            spins = SPINS;       // releaser hasn't set match yet
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   394
                        else if (!t.isInterrupted() && m == 0 &&
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   395
                                 (!timed ||
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   396
                                  (ns = end - System.nanoTime()) > 0L)) {
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   397
                            p.parked = t;              // minimize window
39725
9548f8d846e9 8080603: Replace Unsafe with VarHandle in java.util.concurrent classes
dl
parents: 36936
diff changeset
   398
                            if (AA.getAcquire(a, j) == p) {
9548f8d846e9 8080603: Replace Unsafe with VarHandle in java.util.concurrent classes
dl
parents: 36936
diff changeset
   399
                                if (ns == 0L)
9548f8d846e9 8080603: Replace Unsafe with VarHandle in java.util.concurrent classes
dl
parents: 36936
diff changeset
   400
                                    LockSupport.park(this);
9548f8d846e9 8080603: Replace Unsafe with VarHandle in java.util.concurrent classes
dl
parents: 36936
diff changeset
   401
                                else
9548f8d846e9 8080603: Replace Unsafe with VarHandle in java.util.concurrent classes
dl
parents: 36936
diff changeset
   402
                                    LockSupport.parkNanos(this, ns);
9548f8d846e9 8080603: Replace Unsafe with VarHandle in java.util.concurrent classes
dl
parents: 36936
diff changeset
   403
                            }
18768
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   404
                            p.parked = null;
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   405
                        }
39725
9548f8d846e9 8080603: Replace Unsafe with VarHandle in java.util.concurrent classes
dl
parents: 36936
diff changeset
   406
                        else if (AA.getAcquire(a, j) == p &&
9548f8d846e9 8080603: Replace Unsafe with VarHandle in java.util.concurrent classes
dl
parents: 36936
diff changeset
   407
                                 AA.compareAndSet(a, j, p, null)) {
18768
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   408
                            if (m != 0)                // try to shrink
39725
9548f8d846e9 8080603: Replace Unsafe with VarHandle in java.util.concurrent classes
dl
parents: 36936
diff changeset
   409
                                BOUND.compareAndSet(this, b, b + SEQ - 1);
18768
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   410
                            p.item = null;
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   411
                            p.hash = h;
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   412
                            i = p.index >>>= 1;        // descend
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   413
                            if (Thread.interrupted())
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   414
                                return null;
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   415
                            if (timed && m == 0 && ns <= 0L)
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   416
                                return TIMED_OUT;
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   417
                            break;                     // expired; restart
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   418
                        }
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   419
                    }
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   420
                }
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   421
                else
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   422
                    p.item = null;                     // clear offer
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   423
            }
18768
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   424
            else {
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   425
                if (p.bound != b) {                    // stale; reset
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   426
                    p.bound = b;
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   427
                    p.collides = 0;
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   428
                    i = (i != m || m == 0) ? m : m - 1;
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   429
                }
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   430
                else if ((c = p.collides) < m || m == FULL ||
39725
9548f8d846e9 8080603: Replace Unsafe with VarHandle in java.util.concurrent classes
dl
parents: 36936
diff changeset
   431
                         !BOUND.compareAndSet(this, b, b + SEQ + 1)) {
18768
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   432
                    p.collides = c + 1;
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   433
                    i = (i == 0) ? m : i - 1;          // cyclically traverse
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   434
                }
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   435
                else
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   436
                    i = m + 1;                         // grow
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   437
                p.index = i;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   438
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   439
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   440
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   441
90ce3da70b43 Initial load
duke
parents:
diff changeset
   442
    /**
18768
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   443
     * Exchange function used until arenas enabled. See above for explanation.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   444
     *
18768
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   445
     * @param item the item to exchange
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   446
     * @param timed true if the wait is timed
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   447
     * @param ns if timed, the maximum wait time, else 0L
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   448
     * @return the other thread's item; or null if either the arena
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   449
     * was enabled or the thread was interrupted before completion; or
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   450
     * TIMED_OUT if timed and timed out
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   451
     */
18768
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   452
    private final Object slotExchange(Object item, boolean timed, long ns) {
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   453
        Node p = participant.get();
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   454
        Thread t = Thread.currentThread();
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   455
        if (t.isInterrupted()) // preserve interrupt status so caller can recheck
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   456
            return null;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   457
18768
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   458
        for (Node q;;) {
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   459
            if ((q = slot) != null) {
39725
9548f8d846e9 8080603: Replace Unsafe with VarHandle in java.util.concurrent classes
dl
parents: 36936
diff changeset
   460
                if (SLOT.compareAndSet(this, q, null)) {
18768
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   461
                    Object v = q.item;
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   462
                    q.match = item;
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   463
                    Thread w = q.parked;
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   464
                    if (w != null)
39725
9548f8d846e9 8080603: Replace Unsafe with VarHandle in java.util.concurrent classes
dl
parents: 36936
diff changeset
   465
                        LockSupport.unpark(w);
18768
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   466
                    return v;
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   467
                }
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   468
                // create arena on contention, but continue until slot null
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   469
                if (NCPU > 1 && bound == 0 &&
39725
9548f8d846e9 8080603: Replace Unsafe with VarHandle in java.util.concurrent classes
dl
parents: 36936
diff changeset
   470
                    BOUND.compareAndSet(this, 0, SEQ))
18768
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   471
                    arena = new Node[(FULL + 2) << ASHIFT];
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   472
            }
18768
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   473
            else if (arena != null)
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   474
                return null; // caller must reroute to arenaExchange
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   475
            else {
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   476
                p.item = item;
39725
9548f8d846e9 8080603: Replace Unsafe with VarHandle in java.util.concurrent classes
dl
parents: 36936
diff changeset
   477
                if (SLOT.compareAndSet(this, null, p))
18768
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   478
                    break;
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   479
                p.item = null;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   480
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   481
        }
18768
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   482
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   483
        // await release
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   484
        int h = p.hash;
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   485
        long end = timed ? System.nanoTime() + ns : 0L;
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   486
        int spins = (NCPU > 1) ? SPINS : 1;
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   487
        Object v;
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   488
        while ((v = p.match) == null) {
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   489
            if (spins > 0) {
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   490
                h ^= h << 1; h ^= h >>> 3; h ^= h << 10;
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   491
                if (h == 0)
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   492
                    h = SPINS | (int)t.getId();
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   493
                else if (h < 0 && (--spins & ((SPINS >>> 1) - 1)) == 0)
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   494
                    Thread.yield();
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   495
            }
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   496
            else if (slot != p)
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   497
                spins = SPINS;
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   498
            else if (!t.isInterrupted() && arena == null &&
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   499
                     (!timed || (ns = end - System.nanoTime()) > 0L)) {
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   500
                p.parked = t;
39725
9548f8d846e9 8080603: Replace Unsafe with VarHandle in java.util.concurrent classes
dl
parents: 36936
diff changeset
   501
                if (slot == p) {
9548f8d846e9 8080603: Replace Unsafe with VarHandle in java.util.concurrent classes
dl
parents: 36936
diff changeset
   502
                    if (ns == 0L)
9548f8d846e9 8080603: Replace Unsafe with VarHandle in java.util.concurrent classes
dl
parents: 36936
diff changeset
   503
                        LockSupport.park(this);
9548f8d846e9 8080603: Replace Unsafe with VarHandle in java.util.concurrent classes
dl
parents: 36936
diff changeset
   504
                    else
9548f8d846e9 8080603: Replace Unsafe with VarHandle in java.util.concurrent classes
dl
parents: 36936
diff changeset
   505
                        LockSupport.parkNanos(this, ns);
9548f8d846e9 8080603: Replace Unsafe with VarHandle in java.util.concurrent classes
dl
parents: 36936
diff changeset
   506
                }
18768
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   507
                p.parked = null;
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   508
            }
39725
9548f8d846e9 8080603: Replace Unsafe with VarHandle in java.util.concurrent classes
dl
parents: 36936
diff changeset
   509
            else if (SLOT.compareAndSet(this, p, null)) {
18768
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   510
                v = timed && ns <= 0L && !t.isInterrupted() ? TIMED_OUT : null;
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   511
                break;
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   512
            }
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   513
        }
39725
9548f8d846e9 8080603: Replace Unsafe with VarHandle in java.util.concurrent classes
dl
parents: 36936
diff changeset
   514
        MATCH.setRelease(p, null);
18768
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   515
        p.item = null;
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   516
        p.hash = h;
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   517
        return v;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   518
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   519
90ce3da70b43 Initial load
duke
parents:
diff changeset
   520
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   521
     * Creates a new Exchanger.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   522
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   523
    public Exchanger() {
18768
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   524
        participant = new Participant();
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   525
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   526
90ce3da70b43 Initial load
duke
parents:
diff changeset
   527
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   528
     * Waits for another thread to arrive at this exchange point (unless
90ce3da70b43 Initial load
duke
parents:
diff changeset
   529
     * the current thread is {@linkplain Thread#interrupt interrupted}),
90ce3da70b43 Initial load
duke
parents:
diff changeset
   530
     * and then transfers the given object to it, receiving its object
90ce3da70b43 Initial load
duke
parents:
diff changeset
   531
     * in return.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   532
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   533
     * <p>If another thread is already waiting at the exchange point then
90ce3da70b43 Initial load
duke
parents:
diff changeset
   534
     * it is resumed for thread scheduling purposes and receives the object
90ce3da70b43 Initial load
duke
parents:
diff changeset
   535
     * passed in by the current thread.  The current thread returns immediately,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   536
     * receiving the object passed to the exchange by that other thread.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   537
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   538
     * <p>If no other thread is already waiting at the exchange then the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   539
     * current thread is disabled for thread scheduling purposes and lies
90ce3da70b43 Initial load
duke
parents:
diff changeset
   540
     * dormant until one of two things happens:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   541
     * <ul>
90ce3da70b43 Initial load
duke
parents:
diff changeset
   542
     * <li>Some other thread enters the exchange; or
7518
0282db800fe1 7003745: Code style cleanups (sync from Dougs CVS)
dl
parents: 5506
diff changeset
   543
     * <li>Some other thread {@linkplain Thread#interrupt interrupts}
0282db800fe1 7003745: Code style cleanups (sync from Dougs CVS)
dl
parents: 5506
diff changeset
   544
     * the current thread.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   545
     * </ul>
90ce3da70b43 Initial load
duke
parents:
diff changeset
   546
     * <p>If the current thread:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   547
     * <ul>
90ce3da70b43 Initial load
duke
parents:
diff changeset
   548
     * <li>has its interrupted status set on entry to this method; or
90ce3da70b43 Initial load
duke
parents:
diff changeset
   549
     * <li>is {@linkplain Thread#interrupt interrupted} while waiting
90ce3da70b43 Initial load
duke
parents:
diff changeset
   550
     * for the exchange,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   551
     * </ul>
90ce3da70b43 Initial load
duke
parents:
diff changeset
   552
     * then {@link InterruptedException} is thrown and the current thread's
90ce3da70b43 Initial load
duke
parents:
diff changeset
   553
     * interrupted status is cleared.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   554
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   555
     * @param x the object to exchange
90ce3da70b43 Initial load
duke
parents:
diff changeset
   556
     * @return the object provided by the other thread
90ce3da70b43 Initial load
duke
parents:
diff changeset
   557
     * @throws InterruptedException if the current thread was
90ce3da70b43 Initial load
duke
parents:
diff changeset
   558
     *         interrupted while waiting
90ce3da70b43 Initial load
duke
parents:
diff changeset
   559
     */
11279
d9dab5ec5044 7118066: Warnings in java.util.concurrent package
dl
parents: 9242
diff changeset
   560
    @SuppressWarnings("unchecked")
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   561
    public V exchange(V x) throws InterruptedException {
18768
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   562
        Object v;
39725
9548f8d846e9 8080603: Replace Unsafe with VarHandle in java.util.concurrent classes
dl
parents: 36936
diff changeset
   563
        Node[] a;
18768
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   564
        Object item = (x == null) ? NULL_ITEM : x; // translate null args
39725
9548f8d846e9 8080603: Replace Unsafe with VarHandle in java.util.concurrent classes
dl
parents: 36936
diff changeset
   565
        if (((a = arena) != null ||
18768
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   566
             (v = slotExchange(item, false, 0L)) == null) &&
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   567
            ((Thread.interrupted() || // disambiguates null return
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   568
              (v = arenaExchange(item, false, 0L)) == null)))
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   569
            throw new InterruptedException();
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   570
        return (v == NULL_ITEM) ? null : (V)v;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   571
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   572
90ce3da70b43 Initial load
duke
parents:
diff changeset
   573
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   574
     * Waits for another thread to arrive at this exchange point (unless
90ce3da70b43 Initial load
duke
parents:
diff changeset
   575
     * the current thread is {@linkplain Thread#interrupt interrupted} or
90ce3da70b43 Initial load
duke
parents:
diff changeset
   576
     * the specified waiting time elapses), and then transfers the given
90ce3da70b43 Initial load
duke
parents:
diff changeset
   577
     * object to it, receiving its object in return.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   578
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   579
     * <p>If another thread is already waiting at the exchange point then
90ce3da70b43 Initial load
duke
parents:
diff changeset
   580
     * it is resumed for thread scheduling purposes and receives the object
90ce3da70b43 Initial load
duke
parents:
diff changeset
   581
     * passed in by the current thread.  The current thread returns immediately,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   582
     * receiving the object passed to the exchange by that other thread.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   583
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   584
     * <p>If no other thread is already waiting at the exchange then the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   585
     * current thread is disabled for thread scheduling purposes and lies
90ce3da70b43 Initial load
duke
parents:
diff changeset
   586
     * dormant until one of three things happens:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   587
     * <ul>
90ce3da70b43 Initial load
duke
parents:
diff changeset
   588
     * <li>Some other thread enters the exchange; or
90ce3da70b43 Initial load
duke
parents:
diff changeset
   589
     * <li>Some other thread {@linkplain Thread#interrupt interrupts}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   590
     * the current thread; or
90ce3da70b43 Initial load
duke
parents:
diff changeset
   591
     * <li>The specified waiting time elapses.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   592
     * </ul>
90ce3da70b43 Initial load
duke
parents:
diff changeset
   593
     * <p>If the current thread:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   594
     * <ul>
90ce3da70b43 Initial load
duke
parents:
diff changeset
   595
     * <li>has its interrupted status set on entry to this method; or
90ce3da70b43 Initial load
duke
parents:
diff changeset
   596
     * <li>is {@linkplain Thread#interrupt interrupted} while waiting
90ce3da70b43 Initial load
duke
parents:
diff changeset
   597
     * for the exchange,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   598
     * </ul>
90ce3da70b43 Initial load
duke
parents:
diff changeset
   599
     * then {@link InterruptedException} is thrown and the current thread's
90ce3da70b43 Initial load
duke
parents:
diff changeset
   600
     * interrupted status is cleared.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   601
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   602
     * <p>If the specified waiting time elapses then {@link
90ce3da70b43 Initial load
duke
parents:
diff changeset
   603
     * TimeoutException} is thrown.  If the time is less than or equal
90ce3da70b43 Initial load
duke
parents:
diff changeset
   604
     * to zero, the method will not wait at all.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   605
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   606
     * @param x the object to exchange
90ce3da70b43 Initial load
duke
parents:
diff changeset
   607
     * @param timeout the maximum time to wait
18768
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   608
     * @param unit the time unit of the {@code timeout} argument
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   609
     * @return the object provided by the other thread
90ce3da70b43 Initial load
duke
parents:
diff changeset
   610
     * @throws InterruptedException if the current thread was
90ce3da70b43 Initial load
duke
parents:
diff changeset
   611
     *         interrupted while waiting
90ce3da70b43 Initial load
duke
parents:
diff changeset
   612
     * @throws TimeoutException if the specified waiting time elapses
90ce3da70b43 Initial load
duke
parents:
diff changeset
   613
     *         before another thread enters the exchange
90ce3da70b43 Initial load
duke
parents:
diff changeset
   614
     */
11279
d9dab5ec5044 7118066: Warnings in java.util.concurrent package
dl
parents: 9242
diff changeset
   615
    @SuppressWarnings("unchecked")
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   616
    public V exchange(V x, long timeout, TimeUnit unit)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   617
        throws InterruptedException, TimeoutException {
18768
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   618
        Object v;
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   619
        Object item = (x == null) ? NULL_ITEM : x;
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   620
        long ns = unit.toNanos(timeout);
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   621
        if ((arena != null ||
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   622
             (v = slotExchange(item, true, ns)) == null) &&
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   623
            ((Thread.interrupted() ||
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   624
              (v = arenaExchange(item, true, ns)) == null)))
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   625
            throw new InterruptedException();
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   626
        if (v == TIMED_OUT)
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   627
            throw new TimeoutException();
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   628
        return (v == NULL_ITEM) ? null : (V)v;
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   629
    }
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   630
39725
9548f8d846e9 8080603: Replace Unsafe with VarHandle in java.util.concurrent classes
dl
parents: 36936
diff changeset
   631
    // VarHandle mechanics
9548f8d846e9 8080603: Replace Unsafe with VarHandle in java.util.concurrent classes
dl
parents: 36936
diff changeset
   632
    private static final VarHandle BOUND;
9548f8d846e9 8080603: Replace Unsafe with VarHandle in java.util.concurrent classes
dl
parents: 36936
diff changeset
   633
    private static final VarHandle SLOT;
9548f8d846e9 8080603: Replace Unsafe with VarHandle in java.util.concurrent classes
dl
parents: 36936
diff changeset
   634
    private static final VarHandle MATCH;
9548f8d846e9 8080603: Replace Unsafe with VarHandle in java.util.concurrent classes
dl
parents: 36936
diff changeset
   635
    private static final VarHandle AA;
18768
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   636
    static {
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   637
        try {
39725
9548f8d846e9 8080603: Replace Unsafe with VarHandle in java.util.concurrent classes
dl
parents: 36936
diff changeset
   638
            MethodHandles.Lookup l = MethodHandles.lookup();
9548f8d846e9 8080603: Replace Unsafe with VarHandle in java.util.concurrent classes
dl
parents: 36936
diff changeset
   639
            BOUND = l.findVarHandle(Exchanger.class, "bound", int.class);
9548f8d846e9 8080603: Replace Unsafe with VarHandle in java.util.concurrent classes
dl
parents: 36936
diff changeset
   640
            SLOT = l.findVarHandle(Exchanger.class, "slot", Node.class);
9548f8d846e9 8080603: Replace Unsafe with VarHandle in java.util.concurrent classes
dl
parents: 36936
diff changeset
   641
            MATCH = l.findVarHandle(Node.class, "match", Object.class);
9548f8d846e9 8080603: Replace Unsafe with VarHandle in java.util.concurrent classes
dl
parents: 36936
diff changeset
   642
            AA = MethodHandles.arrayElementVarHandle(Node[].class);
32991
b27c76b82713 8134853: Bulk integration of java.util.concurrent classes
dl
parents: 25859
diff changeset
   643
        } catch (ReflectiveOperationException e) {
18768
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   644
            throw new Error(e);
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   645
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   646
    }
18768
f2638f396c41 8019481: Sync misc j.u.c classes from 166 to tl
psandoz
parents: 11279
diff changeset
   647
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   648
}