< prev index next >

src/java.base/share/classes/java/util/concurrent/atomic/DoubleAccumulator.java

Print this page
8192943: Optimize atomic accumulators using VarHandle getAndSet
Reviewed-by: martin, psandoz, chegar


  88     private final long identity; // use long representation
  89 
  90     /**
  91      * Creates a new instance using the given accumulator function
  92      * and identity element.
  93      * @param accumulatorFunction a side-effect-free function of two arguments
  94      * @param identity identity (initial value) for the accumulator function
  95      */
  96     public DoubleAccumulator(DoubleBinaryOperator accumulatorFunction,
  97                              double identity) {
  98         this.function = accumulatorFunction;
  99         base = this.identity = doubleToRawLongBits(identity);
 100     }
 101 
 102     /**
 103      * Updates with the given value.
 104      *
 105      * @param x the value
 106      */
 107     public void accumulate(double x) {
 108         Cell[] as; long b, v, r; int m; Cell a;
 109         if ((as = cells) != null
 110             || ((r = doubleToRawLongBits
 111                 (function.applyAsDouble(longBitsToDouble(b = base), x))) != b
 112                 && !casBase(b, r))) {
 113             boolean uncontended = true;
 114             if (as == null
 115                 || (m = as.length - 1) < 0
 116                 || (a = as[getProbe() & m]) == null
 117                 || !(uncontended =
 118                      ((r = doubleToRawLongBits
 119                        (function.applyAsDouble
 120                         (longBitsToDouble(v = a.value), x))) == v)
 121                      || a.cas(v, r)))
 122                 doubleAccumulate(x, function, uncontended);
 123         }
 124     }
 125 
 126     /**
 127      * Returns the current value.  The returned value is <em>NOT</em>
 128      * an atomic snapshot; invocation in the absence of concurrent
 129      * updates returns an accurate result, but concurrent updates that
 130      * occur while the value is being calculated might not be
 131      * incorporated.
 132      *
 133      * @return the current value
 134      */
 135     public double get() {
 136         Cell[] as = cells;
 137         double result = longBitsToDouble(base);
 138         if (as != null) {
 139             for (Cell a : as)
 140                 if (a != null)
 141                     result = function.applyAsDouble
 142                         (result, longBitsToDouble(a.value));
 143         }
 144         return result;
 145     }
 146 
 147     /**
 148      * Resets variables maintaining updates to the identity value.
 149      * This method may be a useful alternative to creating a new
 150      * updater, but is only effective if there are no concurrent
 151      * updates.  Because this method is intrinsically racy, it should
 152      * only be used when it is known that no threads are concurrently
 153      * updating.
 154      */
 155     public void reset() {
 156         Cell[] as = cells;
 157         base = identity;
 158         if (as != null) {
 159             for (Cell a : as)
 160                 if (a != null)
 161                     a.reset(identity);
 162         }
 163     }
 164 
 165     /**
 166      * Equivalent in effect to {@link #get} followed by {@link
 167      * #reset}. This method may apply for example during quiescent
 168      * points between multithreaded computations.  If there are
 169      * updates concurrent with this method, the returned value is
 170      * <em>not</em> guaranteed to be the final value occurring before
 171      * the reset.
 172      *
 173      * @return the value before reset
 174      */
 175     public double getThenReset() {
 176         Cell[] as = cells;
 177         double result = longBitsToDouble(base);
 178         base = identity;
 179         if (as != null) {
 180             for (Cell a : as) {
 181                 if (a != null) {
 182                     double v = longBitsToDouble(a.value);
 183                     a.reset(identity);
 184                     result = function.applyAsDouble(result, v);
 185                 }
 186             }
 187         }
 188         return result;
 189     }
 190 
 191     /**
 192      * Returns the String representation of the current value.
 193      * @return the String representation of the current value
 194      */
 195     public String toString() {
 196         return Double.toString(get());
 197     }
 198 
 199     /**
 200      * Equivalent to {@link #get}.
 201      *
 202      * @return the current value
 203      */




  88     private final long identity; // use long representation
  89 
  90     /**
  91      * Creates a new instance using the given accumulator function
  92      * and identity element.
  93      * @param accumulatorFunction a side-effect-free function of two arguments
  94      * @param identity identity (initial value) for the accumulator function
  95      */
  96     public DoubleAccumulator(DoubleBinaryOperator accumulatorFunction,
  97                              double identity) {
  98         this.function = accumulatorFunction;
  99         base = this.identity = doubleToRawLongBits(identity);
 100     }
 101 
 102     /**
 103      * Updates with the given value.
 104      *
 105      * @param x the value
 106      */
 107     public void accumulate(double x) {
 108         Cell[] cs; long b, v, r; int m; Cell c;
 109         if ((cs = cells) != null
 110             || ((r = doubleToRawLongBits
 111                 (function.applyAsDouble(longBitsToDouble(b = base), x))) != b
 112                 && !casBase(b, r))) {
 113             boolean uncontended = true;
 114             if (cs == null
 115                 || (m = cs.length - 1) < 0
 116                 || (c = cs[getProbe() & m]) == null
 117                 || !(uncontended =
 118                      ((r = doubleToRawLongBits
 119                        (function.applyAsDouble
 120                         (longBitsToDouble(v = c.value), x))) == v)
 121                      || c.cas(v, r)))
 122                 doubleAccumulate(x, function, uncontended);
 123         }
 124     }
 125 
 126     /**
 127      * Returns the current value.  The returned value is <em>NOT</em>
 128      * an atomic snapshot; invocation in the absence of concurrent
 129      * updates returns an accurate result, but concurrent updates that
 130      * occur while the value is being calculated might not be
 131      * incorporated.
 132      *
 133      * @return the current value
 134      */
 135     public double get() {
 136         Cell[] cs = cells;
 137         double result = longBitsToDouble(base);
 138         if (cs != null) {
 139             for (Cell c : cs)
 140                 if (c != null)
 141                     result = function.applyAsDouble
 142                         (result, longBitsToDouble(c.value));
 143         }
 144         return result;
 145     }
 146 
 147     /**
 148      * Resets variables maintaining updates to the identity value.
 149      * This method may be a useful alternative to creating a new
 150      * updater, but is only effective if there are no concurrent
 151      * updates.  Because this method is intrinsically racy, it should
 152      * only be used when it is known that no threads are concurrently
 153      * updating.
 154      */
 155     public void reset() {
 156         Cell[] cs = cells;
 157         base = identity;
 158         if (cs != null) {
 159             for (Cell c : cs)
 160                 if (c != null)
 161                     c.reset(identity);
 162         }
 163     }
 164 
 165     /**
 166      * Equivalent in effect to {@link #get} followed by {@link
 167      * #reset}. This method may apply for example during quiescent
 168      * points between multithreaded computations.  If there are
 169      * updates concurrent with this method, the returned value is
 170      * <em>not</em> guaranteed to be the final value occurring before
 171      * the reset.
 172      *
 173      * @return the value before reset
 174      */
 175     public double getThenReset() {
 176         Cell[] cs = cells;
 177         double result = longBitsToDouble(getAndSetBase(identity));
 178         if (cs != null) {
 179             for (Cell c : cs) {
 180                 if (c != null) {
 181                     double v = longBitsToDouble(c.getAndSet(identity));


 182                     result = function.applyAsDouble(result, v);
 183                 }
 184             }
 185         }
 186         return result;
 187     }
 188 
 189     /**
 190      * Returns the String representation of the current value.
 191      * @return the String representation of the current value
 192      */
 193     public String toString() {
 194         return Double.toString(get());
 195     }
 196 
 197     /**
 198      * Equivalent to {@link #get}.
 199      *
 200      * @return the current value
 201      */


< prev index next >